diff --git a/library/GSM_RR_Types.ttcn b/library/GSM_RR_Types.ttcn index 965708f9b..f5eeda5cf 100644 --- a/library/GSM_RR_Types.ttcn +++ b/library/GSM_RR_Types.ttcn @@ -911,6 +911,22 @@ module GSM_RR_Types { } }; + template GsmRrMessage tr_PAG_REQ1(template MobileIdentityLV mi1 := ?) := { + header := t_RrHeader(PAGING_REQUEST_TYPE_1, ?), + payload := { + pag_req_1 := { + chan_needed := { + second := ?, + first := ? + }, + page_mode := PAGE_MODE_NORMAL, + mi1 := mi1, + mi2 := omit, + rest_octets := ? + } + } + }; + template (value) GsmRrL3Message ts_MEAS_REP(boolean valid, uint6_t rxl_f, uint6_t rxl_s, uint3_t rxq_f, uint3_t rxq_s, template (omit) NcellReports reps) := { diff --git a/library/Osmocom_Gb_Types.ttcn b/library/Osmocom_Gb_Types.ttcn index 55a2816f7..3149e7721 100644 --- a/library/Osmocom_Gb_Types.ttcn +++ b/library/Osmocom_Gb_Types.ttcn @@ -1121,6 +1121,18 @@ octetstring sdu) := { delay_Value := f_oct_or_wc(delay, 2) } + template DRX_Parameters t_defaultDRXparam := { + iEI := '0A'O, + ext := '1'B, + lengthIndicator := { + length1 := 2 + }, + splitPG_CycleCode := '00'O, + nonDRXTimer := '000'B, + splitOnCCCH := '0'B, + cnSpecificDRXCycleLength := '0000'B + } + template PDU_BSSGP ts_BSSGP_DL_UD(GprsTlli tlli, octetstring pdu) := { pDU_BSSGP_DL_UNITDATA := { bssgpPduType := '00'O, @@ -1220,6 +1232,38 @@ octetstring sdu) := { } } + template PDU_BSSGP tr_BSSGP_CS_PAGING(BssgpBvci bvci) := { + pDU_BSSGP_PAGING_CS := { + bssgpPduType := '07'O, + iMSI := ?, + dRX_Parameters := ?, + paging_Field4 := { + bVCI := t_BSSGP_BVCI(bvci) + }, + tLLI := *, + channel_needed := *, + eMLPP_Priority := *, + tMSI := *, + global_CN_Id := * + } + } + + template PDU_BSSGP ts_BSSGP_CS_PAGING_IMSI(BssgpBvci bvci, hexstring imsi) := { + pDU_BSSGP_PAGING_CS := { + bssgpPduType := '07'O, + iMSI := ts_BSSGP_IMSI(imsi), + dRX_Parameters := t_defaultDRXparam, + paging_Field4 := { + bVCI := t_BSSGP_BVCI(bvci) + }, + tLLI := omit, + channel_needed := omit, + eMLPP_Priority := omit, + tMSI := omit, + global_CN_Id := omit + } + } + template PDU_BSSGP tr_BSSGP_PS_PAGING(BssgpBvci bvci) := { pDU_BSSGP_PAGING_PS := { bssgpPduType := '06'O, diff --git a/pcu/PCU_Tests_RAW.ttcn b/pcu/PCU_Tests_RAW.ttcn index c41a24420..ff609fe9e 100644 --- a/pcu/PCU_Tests_RAW.ttcn +++ b/pcu/PCU_Tests_RAW.ttcn @@ -738,6 +738,24 @@ runs on RAW_PCU_Test_CT { fn := 0, arfcn := 871, sapi := PCU_IF_SAPI_PCH, data := macblock)); } +/* Expect a Paging Request Type 1 from PCU on PCUIF on specified sapi. */ +private function f_pcuif_rx_pch_pag_req1(out GsmRrMessage rr_pag_req1) +runs on RAW_PCU_Test_CT { + var PCUIF_Message pcu_msg; + var octetstring macblock; + BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0, + sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg; + /* First 3 bytes contain paging group: */ + macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3); + rr_pag_req1 := dec_GsmRrMessage(macblock); + if (not match(rr_pag_req1, tr_PAG_REQ1())) { + setverdict(fail, "Failed to match Paging Request Type 1: ", rr_pag_req1); + mtc.stop; + } + BTS.send(ts_PCUIF_DATA_CNF(bts_nr := 0, trx_nr := 0, ts_nr := 0, block_nr := 0, + fn := pcu_msg.u.data_req.fn, arfcn := 871, sapi := PCU_IF_SAPI_PCH, data := macblock)); +} + private function f_tx_rlcmac_ul_block(template (value) RlcmacUlBlock ul_data, int16_t lqual_cb := 0, uint32_t fn := 0) runs on RAW_PCU_Test_CT { var octetstring data; @@ -1666,6 +1684,95 @@ testcase TC_paging_cs_from_bts() runs on RAW_PCU_Test_CT { setverdict(pass); } +/* Test CS paging over Gb (SGSN->PCU->BTS[PDCH]). + */ +private function f_tc_paging_cs_from_sgsn(Nsvci bvci) runs on RAW_PCU_Test_CT { + var GsmRrMessage rr_imm_ass; + var PacketUlAssign ul_tbf_ass; + var RlcmacDlBlock dl_block; + var boolean ok; + var OCT4 tlli := '00000001'O; + var MobileIdentityLV_Paging mi_res; + var hexstring imsi := f_gen_imsi(42); + + /* Initialize NS/BSSGP side */ + f_init_bssgp(); + + /* Initialize the PCU interface abstraction */ + f_init_raw(testcasename()); + + /* Establish BSSGP connection to the PCU */ + f_bssgp_establish(); + f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli); + + /* Establish an Uplink TBF */ + ok := f_establish_tbf(rr_imm_ass); + if (not ok) { + setverdict(fail, "Failed to establish TBF"); + mtc.stop; + } + + ok := f_imm_ass_verify_ul_tbf_ass(rr_imm_ass, ul_tbf_ass); + if (not ok) { + setverdict(fail, "Immediate Assignment not an Uplink TBF"); + mtc.stop; + } + + /* Send paging request */ + BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, imsi)); + + /* Receive it on BTS side towards MS */ + f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block); + + /* FIXME: we must use .ps. here instead of .cs. (the one actually sent) + because TTCN3 counts length up to octet boundary and thinks it's a + PageInfoPs: */ + mi_res := dl_block.ctrl.payload.u.paging.repeated_pageinfo.ps.mobile_identity; + setverdict(pass); +} + +testcase TC_paging_cs_from_sgsn_sign() runs on RAW_PCU_Test_CT { + f_tc_paging_cs_from_sgsn(0); +} + +testcase TC_paging_cs_from_sgsn_ptp() runs on RAW_PCU_Test_CT { + f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvci); +} + +/* Test PS paging over Gb (SGSN->PCU->BTS[CCCH]). + */ +private function f_tc_paging_ps_from_sgsn(Nsvci bvci) runs on RAW_PCU_Test_CT { + var GsmRrMessage rr_pag_req1; + var OCT4 tlli := '00000001'O; + var hexstring imsi := f_gen_imsi(42); + + /* Initialize NS/BSSGP side */ + f_init_bssgp(); + + /* Initialize the PCU interface abstraction */ + f_init_raw(testcasename()); + + /* Establish BSSGP connection to the PCU */ + f_bssgp_establish(); + f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli); + + /* Send paging request */ + BSSGP[0].send(ts_BSSGP_PS_PAGING_IMSI(bvci, imsi)); + + /* Receive it on BTS side towards MS */ + f_pcuif_rx_pch_pag_req1(rr_pag_req1); + + setverdict(pass); +} + +testcase TC_paging_ps_from_sgsn_sign() runs on RAW_PCU_Test_CT { + f_tc_paging_ps_from_sgsn(0); +} + +testcase TC_paging_ps_from_sgsn_ptp() runs on RAW_PCU_Test_CT { + f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci); +} + control { execute( TC_ns_reset() ); execute( TC_ns_reset_retrans() ); @@ -1688,6 +1795,10 @@ control { execute( TC_mo_ping_pong() ); execute( TC_imm_ass_dl_block_retrans() ); execute( TC_paging_cs_from_bts() ); + execute (TC_paging_cs_from_sgsn_sign() ); + execute (TC_paging_cs_from_sgsn_ptp() ); + execute (TC_paging_ps_from_sgsn_sign() ); + execute (TC_paging_ps_from_sgsn_ptp() ); }