Hello Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/7005

to look at the new patch set (#2).

bts: Add PCU Interface testcases

Change-Id: I671b8e2c61705485f46602f648eb5fdc01db12f7
---
M bts/BTS_Tests.default
M bts/BTS_Tests.ttcn
M bts/gen_links.sh
A library/PCUIF_CodecPort.ttcn
A library/PCUIF_Types.ttcn
5 files changed, 881 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks 
refs/changes/05/7005/2

diff --git a/bts/BTS_Tests.default b/bts/BTS_Tests.default
index 562088b..fa8d0b0 100644
--- a/bts/BTS_Tests.default
+++ b/bts/BTS_Tests.default
@@ -13,6 +13,7 @@
 *.BTSVTY.CTRL_READMODE := "buffered"
 *.BTSVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
 *.BTSVTY.PROMPT1 := "OsmoBTS> "
+*.PCU.socket_type := "SEQPACKET"
 
 [MODULE_PARAMETERS]
 Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoBTS";
diff --git a/bts/BTS_Tests.ttcn b/bts/BTS_Tests.ttcn
index 48ca1fd..ddb7e4b 100644
--- a/bts/BTS_Tests.ttcn
+++ b/bts/BTS_Tests.ttcn
@@ -22,6 +22,9 @@
 import from TRXC_CodecPort all;
 import from TRXC_CodecPort_CtrlFunct all;
 
+import from PCUIF_Types all;
+import from PCUIF_CodecPort all;
+
 import from MobileL3_CommonIE_Types all;
 import from MobileL3_RRM_Types all;
 import from MobileL3_Types all;
@@ -43,6 +46,7 @@
        integer mp_rsl_port := 3003;
        integer mp_trx0_arfcn := 871;
        integer mp_bb_trxc_port := 5704;
+       charstring mp_pcu_socket := PCU_SOCK_DEFAULT;
 }
 
 type component test_CT extends CTRL_Adapter_CT {
@@ -61,6 +65,12 @@
        var integer g_bb_trxc_conn_id;
 
        port TELNETasp_PT BTSVTY;
+
+       /* PCU Interface of BTS */
+       port PCUIF_CODEC_PT PCU;
+       var integer g_pcu_conn_id;
+       /* Last PCU INFO IND we received */
+       var PCUIF_Message g_pcu_last_info;
 
        /* SI configuration */
        var SystemInformationConfig si_cfg := {
@@ -212,6 +222,33 @@
        f_vty_transceive(BTSVTY, "enable");
 }
 
+/* PCU socket may at any time receive a new INFO.ind */
+private altstep as_pcu_info_ind() runs on test_CT {
+       var PCUIF_send_data sd;
+       [] PCU.receive(t_SD_PCUIF_MSGT(g_pcu_conn_id, PCU_IF_MSG_INFO_IND)) -> 
value sd {
+               g_pcu_last_info := sd.data;
+               repeat;
+               }
+}
+
+private function f_init_pcu(charstring id) runs on test_CT {
+       timer T := 2.0;
+       var PCUIF_send_data sd;
+       map(self:PCU, system:PCU);
+       g_pcu_conn_id := f_pcuif_connect(PCU, mp_pcu_socket);
+
+       T.start;
+       alt {
+       [] PCU.receive(t_SD_PCUIF_MSGT(g_pcu_conn_id, PCU_IF_MSG_INFO_IND)) -> 
value sd {
+               g_pcu_last_info := sd.data;
+               }
+       [] T.timeout {
+               setverdict(fail, "Timeout waiting for PCU INFO_IND");
+               self.stop;
+               }
+       }
+}
+
 /* global init function */
 function f_init(charstring id := "BTS-Test") runs on test_CT {
        f_init_rsl(id);
@@ -224,6 +261,8 @@
        /* SI2 + SI4 are required for SI testing as they are mandatory defaults 
*/
        f_rsl_bcch_fill(RSL_SYSTEM_INFO_2, ts_SI2_default);
        f_rsl_bcch_fill(RSL_SYSTEM_INFO_4, ts_SI4_default);
+
+       f_init_pcu(id);
 
        /* start with a default moderate timing offset equalling TA=2 */
        f_main_trxc_connect();
@@ -500,6 +539,15 @@
        do {
                ra := f_rnd_octstring(1);
        } while (ra_is_ps(ra));
+       return ra;
+}
+
+/* generate a random RACH for packet-switched */
+private function f_rnd_ra_ps() return OCT1 {
+       var OCT1 ra;
+       do {
+               ra := f_rnd_octstring(1);
+       } while (not ra_is_ps(ra));
        return ra;
 }
 
@@ -1790,6 +1838,309 @@
 }
 
 
+/***********************************************************************
+ * PCU Socket related tests
+ ***********************************************************************/
+
+private function f_TC_pcu_act_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t 
ts_nr, boolean exp_success)
+runs on test_CT {
+       timer T := 3.0;
+
+       /* we don't expect any RTS.req before PDCH are active */
+       T.start;
+       alt {
+       [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr))) {
+               setverdict(fail, "PCU RTS.req before PDCH active?");
+               self.stop;
+               }
+       [] PCU.receive { repeat; }
+       [] T.timeout { }
+       }
+
+       /* Send PDCH activate request for known PDCH timeslot */
+       PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_ACT_REQ(bts_nr, trx_nr, 
ts_nr)));
+
+       /* we now expect RTS.req for this timeslot (only) */
+       T.start;
+       alt {
+       [exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, 
tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
+               setverdict(pass);
+               }
+       [not exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
+                                                tr_PCUIF_RTS_REQ(bts_nr, 
trx_nr, ts_nr))) {
+               setverdict(fail, "Unexpected RTS.req for supposedly failing 
activation");
+               self.stop;
+               }
+       [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ)) {
+               setverdict(fail, "RTS.req for wrong TRX/TS");
+               self.stop;
+               }
+       [] PCU.receive { repeat; }
+       [exp_success] T.timeout {
+               setverdict(fail, "Timeout waiting for PCU RTS.req");
+               }
+       [not exp_success] T.timeout {
+               setverdict(pass);
+               }
+       }
+}
+
+private function f_TC_pcu_deact_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t 
ts_nr)
+runs on test_CT {
+       timer T := 3.0;
+
+       /* Send PDCH activate request for known PDCH timeslot */
+       PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, 
ts_nr)));
+
+       PCU.clear;
+       /* we now expect no RTS.req for this timeslot */
+       T.start;
+       alt {
+       [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr, 
trx_nr, ts_nr))) {
+               setverdict(fail, "Received unexpected PCU RTS.req");
+               self.stop;
+               }
+       [] PCU.receive { repeat; }
+       [] T.timeout {
+               setverdict(pass);
+               }
+       }
+}
+
+/* PDCH activation via PCU socket; check for presence of RTS.req */
+testcase TC_pcu_act_req() runs on test_CT {
+       f_init();
+       f_TC_pcu_act_req(0, 0, 7, true);
+}
+
+/* PDCH activation via PCU socket on non-PDCU timeslot */
+testcase TC_pcu_act_req_wrong_ts() runs on test_CT {
+       f_init();
+       f_TC_pcu_act_req(0, 0, 1, false);
+}
+
+/* PDCH activation via PCU socket on wrong BTS */
+testcase TC_pcu_act_req_wrong_bts() runs on test_CT {
+       f_init();
+       f_TC_pcu_act_req(23, 0, 7, false);
+}
+
+/* PDCH activation via PCU socket on wrong TRX */
+testcase TC_pcu_act_req_wrong_trx() runs on test_CT {
+       f_init();
+       f_TC_pcu_act_req(0, 23, 7, false);
+}
+
+/* PDCH deactivation via PCU socket; check for absence of RTS.req */
+testcase TC_pcu_deact_req() runs on test_CT {
+       f_init();
+       /* Activate PDCH */
+       f_TC_pcu_act_req(0, 0, 7, true);
+       f_sleep(1.0);
+       /* and De-Activate again */
+       f_TC_pcu_deact_req(0, 0, 7);
+}
+
+/* Attempt to deactivate a PDCH on a non-PDCH timeslot */
+testcase TC_pcu_deact_req_wrong_ts() runs on test_CT {
+       f_init();
+       f_TC_pcu_deact_req(0, 0, 1);
+}
+
+/* Test the PCU->BTS Version and BTS->PCU SI13 handshake */
+testcase TC_pcu_ver_si13() runs on test_CT {
+       const octetstring si13 := '00010203040506070909'O;
+       var PCUIF_send_data sd;
+       timer T:= 3.0;
+       f_init();
+
+       /* Set SI13 via RSL */
+       f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, si13);
+       PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_TXT_IND(0, PCU_VERSION, 
"BTS_Test v23")));
+       T.start;
+       alt {
+       [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_DATA_IND(0, 0, 0, ?, 
PCU_IF_SAPI_BCCH))) -> value sd {
+               if (substr(sd.data.u.data_ind.data, 0, lengthof(si13)) == si13) 
{
+                       setverdict(pass);
+               } else {
+                       repeat;
+               }
+               }
+       [] PCU.receive { repeat; }
+       [] T.timeout {
+               setverdict(fail, "Timeout waiting for SI13");
+               self.stop;
+               }
+       }
+}
+
+private const octetstring c_PCU_DATA := 
'000102030405060708090a0b0c0d0e0f10111213141516'O;
+
+/* helper function to send a PCU DATA.req */
+private function f_pcu_data_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
+                               uint8_t block_nr, uint32_t fn, PCUIF_Sapi sapi, 
octetstring data)
+runs on test_CT
+{
+       PCU.send(t_SD_PCUIF(g_pcu_conn_id,
+                       ts_PCUIF_DATA_REQ(bts_nr, trx_nr, ts_nr, block_nr, fn, 
sapi, data)));
+}
+
+/* helper function to wait for RTS.ind for given SAPI on given BTS/TRX/TS and 
then send */
+private function f_pcu_wait_rts_and_data_req(uint8_t bts_nr, uint8_t trx_nr, 
uint8_t ts_nr,
+                                            PCUIF_Sapi sapi, octetstring data)
+runs on test_CT
+{
+       var PCUIF_send_data sd;
+
+       timer T := 3.0;
+       T.start;
+       alt {
+       [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
+                               tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr, sapi))) 
-> value sd {
+               f_pcu_data_req(bts_nr, trx_nr, ts_nr, 
sd.data.u.rts_req.block_nr,
+                                 sd.data.u.rts_req.fn, sapi, data);
+               }
+       [] PCU.receive { repeat; }
+       [] T.timeout {
+               setverdict(fail, "Timeout waiting for RTS.ind");
+               }
+       }
+}
+
+/* Send DATA.req on invalid BTS */
+testcase TC_pcu_data_req_wrong_bts() runs on test_CT {
+       f_init();
+       f_TC_pcu_act_req(0, 0, 7, true);
+       f_pcu_data_req(23, 0, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
+       /* FIXME: how to check this wasn't actually sent and didn't crash BTS? 
*/
+       f_sleep(10.0);
+}
+
+/* Send DATA.req on invalid TRX */
+testcase TC_pcu_data_req_wrong_trx() runs on test_CT {
+       f_init();
+       f_TC_pcu_act_req(0, 0, 7, true);
+       f_pcu_data_req(0, 100, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
+       /* FIXME: how to check this wasn't actually sent and didn't crash BTS? 
*/
+       f_sleep(10.0);
+}
+
+/* Send DATA.req on invalid timeslot */
+testcase TC_pcu_data_req_wrong_ts() runs on test_CT {
+       f_init();
+       f_TC_pcu_act_req(0, 0, 7, true);
+       f_pcu_data_req(0, 0, 70, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
+       /* FIXME: how to check this wasn't actually sent and didn't crash BTS? 
*/
+       f_sleep(10.0);
+}
+
+/* Send DATA.req on timeslot that hasn't been activated */
+testcase TC_pcu_data_req_ts_inactive() runs on test_CT {
+       f_init();
+       f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
+       /* FIXME: how to check this wasn't actually sent and didn't crash BTS? 
*/
+       f_sleep(2.0);
+}
+
+testcase TC_pcu_data_req_pdtch() runs on test_CT {
+       f_init();
+       f_TC_pcu_act_req(0, 0, 7, true);
+       f_pcu_wait_rts_and_data_req(0, 0, 7, PCU_IF_SAPI_PDTCH, c_PCU_DATA);
+       /* FIXME: how to check this was actually sent */
+       f_sleep(2.0);
+}
+
+testcase TC_pcu_data_req_ptcch() runs on test_CT {
+       f_init();
+       f_TC_pcu_act_req(0, 0, 7, true);
+       f_pcu_wait_rts_and_data_req(0, 0, 7, PCU_IF_SAPI_PTCCH, c_PCU_DATA);
+       /* FIXME: how to check this was actually sent */
+       f_sleep(2.0);
+}
+
+/* Send AGCH from PCU; check it appears on Um side */
+testcase TC_pcu_data_req_agch() runs on test_CT {
+       timer T := 3.0;
+       f_init();
+       f_init_l1ctl();
+       f_l1_tune(L1CTL);
+
+       f_TC_pcu_act_req(0, 0, 7, true);
+       f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_AGCH, c_PCU_DATA);
+
+       T.start;
+       alt {
+       [] L1CTL.receive(t_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, 
c_PCU_DATA)) {
+               setverdict(pass);
+               }
+       [] L1CTL.receive { repeat; }
+       [] T.timeout {
+               setverdict(fail, "Timeout waiting for PCU-originated AGCH block 
on Um");
+               }
+       }
+}
+
+/* Send IMM.ASS from PCU for PCH; check it appears on Um side */
+testcase TC_pcu_data_req_imm_ass_pch() runs on test_CT {
+       var octetstring imm_ass := f_rnd_octstring(23);
+       f_init();
+       f_init_l1ctl();
+       f_l1_tune(L1CTL);
+
+       /* append 3 last imsi digits so BTS can compute pagng group */
+       var uint32_t fn := f_PCUIF_tx_imm_ass_pch(PCU, g_pcu_conn_id, imm_ass, 
'123459987'H);
+
+       timer T := 0.5;
+       T.start;
+       alt {
+       [] L1CTL.receive(t_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, imm_ass)) 
{
+               /* TODO: verify paging group */
+               setverdict(pass);
+               }
+       [] L1CTL.receive { repeat; }
+       [] T.timeout {
+               setverdict(fail, "Timeout waiting for PCU-originated AGCH block 
on Um");
+               }
+       }
+}
+
+/* Send RACH from Um side, expect it to show up on PCU socket */
+testcase TC_pcu_rach_content() runs on test_CT {
+       f_init();
+       f_init_l1ctl();
+       f_l1_tune(L1CTL);
+
+       var GsmFrameNumber fn_last := 0;
+       for (var integer i := 0; i < 1000; i := i+1) {
+               var OCT1 ra := f_rnd_ra_ps();
+               var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
+               if (fn == fn_last) {
+                       setverdict(fail, "Two RACH in same FN?!?");
+                       self.stop;
+               }
+               fn_last := fn;
+
+               timer T := 2.0;
+               T.start;
+               alt {
+               [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND(0, 
oct2int(ra), 0, ?, fn))) {
+                       T.stop;
+                       }
+               [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND)) {
+                       setverdict(fail, "Unexpected RACH IND");
+                       self.stop;
+                       }
+               [] PCU.receive { repeat; }
+               [] T.timeout {
+                       setverdict(fail, "Timeout waiting for RACH IND");
+                       self.stop;
+                       }
+               }
+       }
+       setverdict(pass);
+}
+
+
 /* TODO Areas:
 
 * channel activation
@@ -1853,6 +2204,23 @@
        execute( TC_ipa_crcx_mdcx_dlcx_not_active() );
        execute( TC_ipa_crcx_mdcx_mdcx_dlcx_not_active() );
        execute( TC_ipa_crcx_sdcch_not_active() );
+
+       execute( TC_pcu_act_req() );
+       execute( TC_pcu_act_req_wrong_ts() );
+       execute( TC_pcu_act_req_wrong_bts() );
+       execute( TC_pcu_act_req_wrong_trx() );
+       execute( TC_pcu_deact_req() );
+       execute( TC_pcu_deact_req_wrong_ts() );
+       execute( TC_pcu_ver_si13() );
+       execute( TC_pcu_data_req_wrong_bts() );
+       execute( TC_pcu_data_req_wrong_trx() );
+       execute( TC_pcu_data_req_wrong_ts() );
+       execute( TC_pcu_data_req_ts_inactive() );
+       execute( TC_pcu_data_req_pdtch() );
+       execute( TC_pcu_data_req_ptcch() );
+       execute( TC_pcu_data_req_agch() );
+       execute( TC_pcu_data_req_imm_ass_pch() );
+       execute( TC_pcu_rach_content() );
 }
 
 
diff --git a/bts/gen_links.sh b/bts/gen_links.sh
index 253b757..d9c05ff 100755
--- a/bts/gen_links.sh
+++ b/bts/gen_links.sh
@@ -48,4 +48,5 @@
 FILES+="L3_Templates.ttcn L3_Common.ttcn "
 FILES+="Native_Functions.ttcn Native_FunctionDefs.cc "
 FILES+="TRXC_Types.ttcn TRXC_CodecPort.ttcn TRXC_CodecPort_CtrlFunct.ttcn 
TRXC_CodecPort_CtrlFunctDef.cc "
+FILES+="PCUIF_Types.ttcn PCUIF_CodecPort.ttcn "
 gen_links $DIR $FILES
diff --git a/library/PCUIF_CodecPort.ttcn b/library/PCUIF_CodecPort.ttcn
new file mode 100644
index 0000000..fe428af
--- /dev/null
+++ b/library/PCUIF_CodecPort.ttcn
@@ -0,0 +1,114 @@
+module PCUIF_CodecPort {
+
+import from Osmocom_Types all;
+import from PCUIF_Types all;
+import from UD_PortType all;
+import from UD_Types all;
+
+type record PCUIF_send_data {
+       PCUIF_Message   data,
+       integer         id
+};
+
+private function PCUIF_to_UD(in PCUIF_send_data pin, out UD_send_data pout) {
+       pout.id := pin.id;
+       pout.data := enc_PCUIF_Message(pin.data);
+} with { extension "prototype(fast)" };
+
+private function UD_to_PCUIF(in UD_send_data pin, out PCUIF_send_data pout) {
+       pout.id := pin.id;
+       pout.data := dec_PCUIF_Message(pin.data);
+} with { extension "prototype(fast)" };
+
+type port PCUIF_CODEC_PT message {
+       out     UD_close, UD_listen, UD_shutdown, UD_connect, PCUIF_send_data;
+       in      UD_listen_result, UD_connect_result, UD_connected, 
PCUIF_send_data;
+} with { extension "user UD_PT
+       out (
+               UD_close -> UD_close:simple;
+               UD_listen -> UD_listen:simple;
+               UD_shutdown -> UD_shutdown:simple;
+               UD_connect -> UD_connect:simple;
+               PCUIF_send_data -> UD_send_data: function(PCUIF_to_UD)
+               )
+       in (
+               UD_listen_result -> UD_listen_result:simple;
+               UD_connect_result -> UD_connect_result:simple;
+               UD_send_data -> PCUIF_send_data: function(UD_to_PCUIF);
+               UD_connected -> UD_connected:simple
+               )"
+};
+
+template PCUIF_send_data t_SD_PCUIF(integer id, template PCUIF_Message pdu) := 
{
+       data := pdu,
+       id := id
+}
+
+template PCUIF_send_data t_SD_PCUIF_MSGT(integer id, template PCUIF_MsgType 
msg_type,
+                                        template uint8_t bts_nr := ?) := {
+       data := {
+               msg_type := msg_type,
+               bts_nr := bts_nr,
+               spare := ?,
+               u := ?
+       },
+       id := id
+}
+
+function f_pcuif_connect(PCUIF_CODEC_PT pt, charstring sock) return integer {
+       var UD_connect_result res;
+       timer T := 5.0;
+
+       T.start;
+       pt.send(UD_connect:{sock, -1});
+       alt {
+       [] pt.receive(UD_connect_result:?) -> value res {
+               if (ispresent(res.result) and ispresent(res.result.result_code) 
and
+                   res.result.result_code == ERROR) {
+                       setverdict(fail, "Error connecting to PCU socket");
+                       self.stop;
+               } else {
+                       return res.id;
+               }
+               }
+       [] T.timeout {
+               setverdict(fail, "Timeout connecting to PCU socket");
+               self.stop;
+               }
+       }
+       return -23;
+}
+
+function f_PCUIF_tx_imm_ass_pch(PCUIF_CODEC_PT pt, integer conn_id, 
octetstring imm_ass, hexstring imsi,
+                               uint8_t bts_nr := 0) return uint32_t {
+       var PCUIF_send_data sd;
+       timer T := 3.0;
+       /* append 3 last imsi digits so BTS can compute pagng group */
+       var hexstring last_digits := substr(imsi, lengthof(imsi)-3, 3);
+       var octetstring prefix := ''O;
+       log("3 last imsi digits: ", last_digits);
+       for (var integer i := 0; i < 3; i := i+1) {
+               prefix := prefix & int2oct(hex2int('30'H) + 
hex2int(last_digits[i]), 1);
+       }
+       pt.send(t_SD_PCUIF(conn_id,
+                       ts_PCUIF_DATA_REQ(bts_nr, 0, 0, 0, 0, PCU_IF_SAPI_PCH, 
prefix & imm_ass)));
+       T.start;
+       alt {
+       [] pt.receive(t_SD_PCUIF(conn_id,
+                               tr_PCUIF_DATA_CNF(bts_nr, 0, 0, 
PCU_IF_SAPI_PCH))) -> value sd {
+               log("IMM.ASS was sent on fn ", sd.data.u.data_cnf.fn);
+               return sd.data.u.data_cnf.fn;
+               }
+       [] pt.receive { repeat; }
+       [] T.timeout {
+               setverdict(fail, "Timeout waiting for PCU DATA.cnf");
+               self.stop;
+               }
+       }
+       return 0;
+}
+
+
+
+
+}
diff --git a/library/PCUIF_Types.ttcn b/library/PCUIF_Types.ttcn
new file mode 100644
index 0000000..bba5f31
--- /dev/null
+++ b/library/PCUIF_Types.ttcn
@@ -0,0 +1,397 @@
+module PCUIF_Types {
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+/* Osmocom PCU Interface Types, as per 
osmo-pcu/include/osmocom/pcu/pcuif_proto.h */
+
+const charstring PCU_SOCK_DEFAULT := "/tmp/pcu_bts";
+const uint32_t PCU_IF_VERSION := 8;
+
+type enumerated PCUIF_MsgType {
+       PCU_IF_MSG_DATA_REQ             ('00'O),
+       PCU_IF_MSG_DATA_CNF             ('01'O),
+       PCU_IF_MSG_DATA_IND             ('02'O),
+       PCU_IF_MSG_SUSP_REQ             ('03'O),
+       PCU_IF_MSG_RTS_REQ              ('10'O),
+       PCU_IF_MSG_DATA_CNF_DT          ('11'O),
+       PCU_IF_MSG_RACH_IND             ('22'O),
+       PCU_IF_MSG_INFO_IND             ('32'O),
+       PCU_IF_MSG_ACT_REQ              ('40'O),
+       PCU_IF_MSG_TIME_IND             ('52'O),
+       PCU_IF_MSG_PAG_REQ              ('60'O),
+       PCU_IF_MSG_TXT_IND              ('70'O)
+} with { variant "FIELDLENGTH(8)" };
+
+type enumerated PCUIF_Sapi {
+       PCU_IF_SAPI_RACH                ('01'O),
+       PCU_IF_SAPI_AGCH                ('02'O),
+       PCU_IF_SAPI_PCH                 ('03'O),
+       PCU_IF_SAPI_BCCH                ('04'O),
+       PCU_IF_SAPI_PDTCH               ('05'O),
+       PCU_IF_SAPI_PRACH               ('06'O),
+       PCU_IF_SAPI_PTCCH               ('07'O),
+       PCU_IF_SAPI_AGCH_DT             ('08'O)
+} with { variant "FIELDLENGTH(8)" };
+
+type record PCUIF_Flags {
+       boolean         bts_active,
+       boolean         sysmo_direct_dsp,
+       BIT14           spare,
+       boolean         cs1,
+       boolean         cs2,
+       boolean         cs3,
+       boolean         cs4,
+       boolean         mcs1,
+       boolean         mcs2,
+       boolean         mcs3,
+       boolean         mcs4,
+       boolean         mcs5,
+       boolean         mcs6,
+       boolean         mcs7,
+       boolean         mcs8,
+       boolean         mcs9,
+       BIT3            spare2
+} with { variant "" };
+
+type enumerated PCUIF_TextType {
+       PCU_VERSION                     (0),
+       PCU_OML_ALERT                   (1)
+} with { variant "FIELDLENGTH(8)" };
+
+type charstring PCUIF_Text length(128) with { variant "FIELDLENGTH(128)" };
+
+type record PCUIF_txt_ind {
+       PCUIF_TextType  txt_type,
+       PCUIF_Text      text
+} with { variant "" };
+
+type octetstring OCT162 length(162) with { variant "FIELDLENGTH(162)" };
+
+type record PCUIF_data {
+       PCUIF_Sapi      sapi,
+       uint8_t         len,
+       OCT162          data,
+       uint32_t        fn,
+       uint16_t        arfcn,
+       uint8_t         trx_nr,
+       uint8_t         ts_nr,
+       uint8_t         block_nr,
+       int8_t          rssi,
+       uint16_t        ber10k,
+       int16_t         ta_offs_qbits,
+       int16_t         lqual_cb
+} with { variant "" };
+
+type record PCUIF_data_cnf_dt {
+       PCUIF_Sapi      sapi,
+       OCT4            tlli,
+       uint32_t        fn,
+       uint16_t        arfcn,
+       uint8_t         trx_nr,
+       uint8_t         ts_nr,
+       uint8_t         block_nr,
+       int8_t          rssi,
+       uint16_t        ber10k,
+       int16_t         ta_offs_qbits,
+       int16_t         lqual_cb
+} with { variant "" };
+
+type record PCUIF_rts_req {
+       PCUIF_Sapi      sapi,
+       OCT3            spare,
+       uint32_t        fn,
+       uint16_t        arfcn,
+       uint8_t         trx_nr,
+       uint8_t         ts_nr,
+       uint8_t         block_nr
+} with { variant "" };
+
+type record PCUIF_rach_ind {
+       PCUIF_Sapi      sapi,
+       uint16_t        ra,
+       int16_t         qta,
+       uint32_t        fn,
+       uint16_t        arfcn,
+       uint8_t         is_11bit,
+       uint8_t         burst_type
+} with { variant "" };
+
+type record PCUIF_InfoTrx {
+       uint16_t        arfcn,
+       BIT8            pdch_mask,
+       OCT1            spare,
+       OCT8            tsc,
+       uint32_t        hLayer1
+} with { variant "" };
+
+type record PCUIF_info_ind {
+       uint32_t        version,
+       PCUIF_Flags     flags,
+       record length(8) of PCUIF_InfoTrx       trx,
+       uint8_t         bsic,
+
+       uint16_t        mcc,
+       uint16_t        mnc,
+       uint16_t        lac,
+       uint16_t        rac,
+
+       uint16_t        nsei,
+       record length(7) of uint8_t nse_timer,
+       record length(11) of uint8_t cell_timer,
+
+       uint16_t        cell_id,
+       uint16_t        repeat_time,
+       uint8_t         repeat_count,
+       uint16_t        bvci,
+       uint8_t         t3142,
+       uint8_t         t3169,
+       uint8_t         t3191,
+       uint8_t         t3193_10ms,
+       uint8_t         t3195,
+       uint8_t         t3101,
+       uint8_t         t3103,
+       uint8_t         t3105,
+       uint8_t         cv_countdown,
+       uint16_t        dl_tbf_ext,
+       uint16_t        ul_tbf_ext,
+       uint8_t         initial_cs,
+       uint8_t         initial_mcs,
+
+       record length(2) of uint16_t    nsvci,
+       record length(2) of uint16_t    local_pprt,
+       record length(2) of uint16_t    remote_port,
+       record length(2) of uint32_t    remote_ip
+} with { variant "" }
+
+type record PCUIF_act_req {
+       uint8_t         is_activate,
+       uint8_t         trx_nr,
+       uint8_t         ts_nr,
+       OCT1            spare
+} with { variant "" };
+
+type record PCUIF_time_ind {
+       uint32_t        fn
+} with { variant "" };
+
+type record PCUIF_pag_req {
+       PCUIF_Sapi      sapi,
+       uint8_t         chan_needed,
+       OCT9            identity_lv
+} with { variant "" };
+
+type record PCUIF_susp_req {
+       OCT4            tlli,
+       OCT6            ra_id,
+       uint8_t         cause
+} with { variant "" };
+
+
+type union PCUIF_MsgUnion {
+       PCUIF_data              data_req,
+       PCUIF_data              data_cnf,
+       PCUIF_data_cnf_dt       data_cnf_dt,
+       PCUIF_data              data_ind,
+       PCUIF_susp_req          susp_req,
+       PCUIF_rts_req           rts_req,
+       PCUIF_rach_ind          rach_ind,
+       PCUIF_txt_ind           txt_ind,
+       PCUIF_info_ind          info_ind,
+       PCUIF_act_req           act_req,
+       PCUIF_time_ind          time_ind,
+       PCUIF_pag_req           pag_req
+} with { variant "" };
+
+type record PCUIF_Message {
+       PCUIF_MsgType   msg_type,
+       uint8_t         bts_nr,
+       OCT2            spare,
+       PCUIF_MsgUnion  u
+} with { variant (u) "CROSSTAG(
+                               data_req,       msg_type = PCU_IF_MSG_DATA_REQ;
+                               data_cnf,       msg_type = PCU_IF_MSG_DATA_CNF;
+                               data_cnf_dt,    msg_type = 
PCU_IF_MSG_DATA_CNF_DT;
+                               data_ind,       msg_type = PCU_IF_MSG_DATA_IND;
+                               susp_req,       msg_type = PCU_IF_MSG_SUSP_REQ;
+                               rts_req,        msg_type = PCU_IF_MSG_RTS_REQ;
+                               rach_ind,       msg_type = PCU_IF_MSG_RACH_IND;
+                               txt_ind,        msg_type = PCU_IF_MSG_TXT_IND;
+                               info_ind,       msg_type = PCU_IF_MSG_INFO_IND;
+                               act_req,        msg_type = PCU_IF_MSG_ACT_REQ;
+                               time_ind,       msg_type = PCU_IF_MSG_TIME_IND;
+                               pag_req,        msg_type = PCU_IF_MSG_PAG_REQ)"
+        variant "PADDING(1688)"
+};
+
+external function enc_PCUIF_Message(in PCUIF_Message pdu) return octetstring
+       with { extension "prototype(convert) encode(RAW)" };
+external function dec_PCUIF_Message(in octetstring stream) return PCUIF_Message
+       with { extension "prototype(convert) decode(RAW)" };
+
+
+template PCUIF_Message tr_PCUIF_RTS_REQ(template uint8_t bts_nr := ?,
+                                       template uint8_t trx_nr := ?,
+                                       template uint8_t ts_nr := ?,
+                                       template PCUIF_Sapi sapi := ?,
+                                       template uint32_t fn := ?,
+                                       template uint8_t block_nr := ?
+                                       ) := {
+       msg_type := PCU_IF_MSG_RTS_REQ,
+       bts_nr := bts_nr,
+       spare := ?,
+       u := {
+               rts_req := {
+                       sapi := sapi,
+                       spare := ?,
+                       fn := fn,
+                       arfcn := ?,
+                       trx_nr := trx_nr,
+                       ts_nr := ts_nr,
+                       block_nr := block_nr
+               }
+       }
+}
+
+template (value) PCUIF_Message ts_PCUIF_TXT_IND(uint8_t bts_nr, PCUIF_TextType 
tt, charstring text) := {
+       msg_type := PCU_IF_MSG_TXT_IND,
+       bts_nr := bts_nr,
+       spare := '0000'O,
+       u := {
+               txt_ind := {
+                       txt_type := tt,
+                       text := text
+               }
+       }
+}
+
+template (value) PCUIF_Message ts_PCUIF_ACT_REQ(uint8_t bts_nr, uint8_t 
trx_nr, uint8_t ts_nr) := {
+       msg_type := PCU_IF_MSG_ACT_REQ,
+       bts_nr := bts_nr,
+       spare := '0000'O,
+       u := {
+               act_req := {
+                       is_activate := 1,
+                       trx_nr := trx_nr,
+                       ts_nr := ts_nr,
+                       spare := '00'O
+               }
+       }
+}
+
+template (value) PCUIF_Message ts_PCUIF_DEACT_REQ(uint8_t bts_nr, uint8_t 
trx_nr, uint8_t ts_nr) := {
+       msg_type := PCU_IF_MSG_ACT_REQ,
+       bts_nr := bts_nr,
+       spare := '0000'O,
+       u := {
+               act_req := {
+                       is_activate := 0,
+                       trx_nr := trx_nr,
+                       ts_nr := ts_nr,
+                       spare := '00'O
+               }
+       }
+}
+
+template PCUIF_Message tr_PCUIF_DATA_IND(template uint8_t bts_nr := ?,
+                                        template uint8_t trx_nr := ?,
+                                        template uint8_t ts_nr := ?,
+                                        template uint8_t block_nr := ?,
+                                        template PCUIF_Sapi sapi := ?,
+                                        template OCT162 data := ?) := {
+       msg_type := PCU_IF_MSG_DATA_IND,
+       bts_nr := bts_nr,
+       spare := ?,
+       u := {
+               data_ind := {
+                       sapi := sapi,
+                       len := ?,
+                       data := data,
+                       fn := ?,
+                       arfcn := ?,
+                       trx_nr := trx_nr,
+                       ts_nr := ts_nr,
+                       block_nr := block_nr,
+                       rssi := ?,
+                       ber10k := ?,
+                       ta_offs_qbits := ?,
+                       lqual_cb := ?
+               }
+       }
+}
+
+template (value) PCUIF_Message ts_PCUIF_DATA_REQ(uint8_t bts_nr, uint8_t 
trx_nr,
+                                                uint8_t ts_nr, uint8_t 
block_nr,
+                                                uint32_t fn, PCUIF_Sapi sapi,
+                                                octetstring data) := {
+       msg_type := PCU_IF_MSG_DATA_REQ,
+       bts_nr := bts_nr,
+       spare := '0000'O,
+       u := {
+               data_req := {
+                       sapi := sapi,
+                       len := lengthof(data),
+                       data := data,
+                       fn := fn,
+                       arfcn := 0, /* unused in BTS */
+                       trx_nr := trx_nr,
+                       ts_nr := ts_nr,
+                       block_nr := block_nr,
+                       /* measurement parameters below unused on Tx */
+                       rssi := 0,
+                       ber10k := 0,
+                       ta_offs_qbits := 0,
+                       lqual_cb := 0
+               }
+       }
+}
+
+template PCUIF_Message tr_PCUIF_DATA_CNF(template uint8_t bts_nr := ?,
+                                        template uint8_t trx_nr := ?,
+                                        template uint8_t ts_nr := ?,
+                                        template PCUIF_Sapi sapi := ?,
+                                        template octetstring data := ?) := {
+       msg_type := PCU_IF_MSG_DATA_CNF,
+       bts_nr := bts_nr,
+       spare := ?,
+       u := {
+               data_cnf := {
+                       sapi := sapi,
+                       len := ?,
+                       data := data,
+                       fn := ?,
+                       arfcn := ?,
+                       trx_nr := trx_nr,
+                       ts_nr := ts_nr,
+                       block_nr := ?,
+                       rssi := ?,
+                       ber10k := ?,
+                       ta_offs_qbits := ?,
+                       lqual_cb := ?
+               }
+       }
+}
+
+template PCUIF_Message tr_PCUIF_RACH_IND(template uint8_t bts_nr := ?,
+                                        template uint16_t ra := ?,
+                                        template uint8_t is_11bit := ?,
+                                        template uint8_t burst_type := ?,
+                                        template uint32_t fn := ?) := {
+       msg_type := PCU_IF_MSG_RACH_IND,
+       bts_nr := bts_nr,
+       spare := ?,
+       u := {
+               rach_ind := {
+                       sapi := PCU_IF_SAPI_RACH,
+                       ra := ra,
+                       qta := ?,
+                       fn := fn,
+                       arfcn := ?,
+                       is_11bit := is_11bit,
+                       burst_type := burst_type
+               }
+       }
+}
+
+
+} with { encode "RAW" variant "BYTEORDER(first)" };

-- 
To view, visit https://gerrit.osmocom.org/7005
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I671b8e2c61705485f46602f648eb5fdc01db12f7
Gerrit-PatchSet: 2
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <lafo...@gnumonks.org>
Gerrit-Reviewer: Harald Welte <lafo...@gnumonks.org>
Gerrit-Reviewer: Jenkins Builder

Reply via email to