pcu: Test Downlink UNIT_DATA messages from SGSN containing IMSI IE

osmo-pcu.git 0052051c07af63da98137c9f8e3b3119642eb587 introduced a bug
(fixed in 1d68cdff928f32941aff36c70e4543203c283d15) where no MS could
GMM attach to the network, but no test showed the issue.
This couple test verifies both correct behavior and also ensures wrong
IMSI is detected and reported.

Related: OS#4729
Change-Id: I5072d80b7ed9945a6083cdf3254efb8b8f119c54
diff --git a/pcu/PCU_Tests.ttcn b/pcu/PCU_Tests.ttcn
index 3c8be30..9bcf9c6 100644
--- a/pcu/PCU_Tests.ttcn
+++ b/pcu/PCU_Tests.ttcn
@@ -1831,6 +1831,98 @@
 	f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci);
 }
 
+/* Verify osmo-pcu handles DL UNIT_DATA from SGSN with IMSI IE correctly. See OS#4729 */
+testcase TC_bssgp_dl_unitdata_with_valid_imsi() runs on RAW_PCU_Test_CT {
+	var RlcmacDlBlock dl_block;
+	var octetstring data := f_rnd_octstring(10);
+	var uint32_t sched_fn;
+	var uint32_t dl_fn;
+	var GprsMS ms;
+
+	/* Initialize NS/BSSGP side */
+	f_init_bssgp();
+	/* Initialize GPRS MS side */
+	f_init_gprs_ms();
+	ms := g_ms[0]; /* We only use first MS in this test */
+
+	/* 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, ms.tlli);
+
+	/* Establish an Uplink TBF */
+	f_ms_establish_ul_tbf(ms);
+
+	/* Fake GMM GPRS Attach or similar, PCU doesn't care about upper layers here */
+	f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true);
+	f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+	/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+	f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+
+	/* UL block should be received in SGSN */
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+
+	/* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
+	BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+	f_ms_exp_dl_tbf_ass_ccch(ms, PCU_IF_SAPI_PCH);
+
+	/* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+	f_sleep(X2002);
+	f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
+
+	/* ACK the DL block */
+	f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
+	f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+			     f_dl_block_ack_fn(dl_block, dl_fn));
+
+	f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify osmo-pcu acts on incorrect IMSI IE content in DL UNIT_DATA from SGSN. See OS#4729 */
+testcase TC_bssgp_dl_unitdata_with_invalid_imsi() runs on RAW_PCU_Test_CT {
+	var RlcmacDlBlock dl_block;
+	var octetstring data := f_rnd_octstring(10);
+	var uint32_t sched_fn;
+	var uint32_t dl_fn;
+	var GprsMS ms;
+
+	/* Initialize NS/BSSGP side */
+	f_init_bssgp();
+	/* Initialize GPRS MS side */
+	f_init_gprs_ms();
+	ms := g_ms[0]; /* We only use first MS in this test */
+
+	/* 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, ms.tlli);
+
+	/* Establish an Uplink TBF */
+	f_ms_establish_ul_tbf(ms);
+
+	/* Fake GMM GPRS Attach or similar, PCU doesn't care about upper layers here */
+	f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true);
+	f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+	/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+	f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+
+	/* UL block should be received in SGSN */
+	BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+
+	/* Now SGSN sends some DL data with an invalid IMSI */
+	BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI('1122'H)));
+
+	BSSGP_SIG[0].receive(tr_BSSGP_STATUS(omit, BSSGP_CAUSE_CONDITIONAL_IE_ERROR, ?));
+
+	/* TODO: make sure no data is sent over PCU -> MS */
+
+	f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
 private function f_TC_egprs_pkt_chan_req(in EGPRSPktChRequest req,
 					 template GsmRrMessage t_imm_ass := ?,
 					 PCUIF_BurstType bt := BURST_TYPE_1)
@@ -2359,6 +2451,8 @@
 	execute( TC_paging_ps_from_sgsn_sign_ptmsi() );
 	execute( TC_paging_ps_from_sgsn_sign() );
 	execute( TC_paging_ps_from_sgsn_ptp() );
+	execute( TC_bssgp_dl_unitdata_with_valid_imsi() );
+	execute( TC_bssgp_dl_unitdata_with_invalid_imsi() );
 
 	/* EGPRS specific test cases */
 	execute( TC_egprs_pkt_chan_req_signalling() );