mme: Introduce test TC_ue_cell_reselect_geran_to_eutran
This test allows reproducing an idle mobility GERAN->EUTRAN.
Related: OS#6294
Change-Id: I6f8f077b99e83e6467d2b0c05148b81dbcf2ede4
diff --git a/library/NAS_Templates.ttcn b/library/NAS_Templates.ttcn
index 944d857..d45dc7d 100644
--- a/library/NAS_Templates.ttcn
+++ b/library/NAS_Templates.ttcn
@@ -44,6 +44,9 @@
}
const BIT4 c_EPS_SEC_NONE := '0000'B;
+const BIT4 c_EPS_SEC_IP := '0001'B;
+const BIT4 c_EPS_SEC_IP_CIPH := '0010'B;
+
const BIT4 c_EPS_NAS_PD_EMM := '0111'B;
const BIT4 c_EPS_NAS_PD_ESM := '0010'B;
@@ -58,6 +61,16 @@
content := inp
}
+/* 9.9.3.4A - 10.5.1.2/24.008 */
+template (value) CipheringKeySequenceNumberTV
+ts_CipheringKeySequenceNumberTV(template (value) BIT3 key_seq) := {
+ keySequence := {
+ keySequence := key_seq,
+ spare := '0'B
+ },
+ elementIdentifier := '1000'B
+}
+
private template (value) MobileIdentityLV
ts_NAS_MobileIdLV(template (value) MobileIdentityV mid) := {
lengthIndicator := 0,
@@ -178,6 +191,19 @@
ePS_MobileIdentity := ts_NAS_MobileId_GUTI(guti)
}
+/* 9.9.3.25 Nonce */
+template (value) NonceTV
+ts_NonceTV(template (value) OCT4 nonce) := {
+ elementIdentifier := '55'O,
+ noncevalue := nonce
+}
+function f_ts_NonceTV(template (omit) OCT4 nonce) return template (omit) NonceTV {
+ if (istemplatekind(nonce, "omit")) {
+ return omit;
+ }
+ return ts_NonceTV(nonce);
+}
+
/* 9.9.3.26 P-TMSI signature */
template (value) P_TMSISignatureTV
ts_PTMSI_SignatureTV(template (value) OCT3 ptmsi_sig) := {
@@ -408,6 +434,20 @@
}
}
+/* 8.2.27 Tracking Area Update Complete */
+template (value) PDU_NAS_EPS
+ts_PDU_NAS_EPS_TrackingAreaUpdateComplete(template (value) BIT4 securityHeaderType := c_EPS_SEC_NONE) := {
+ protocolDiscriminator := c_EPS_NAS_PD_EMM,
+ ePS_messages := {
+ ePS_MobilityManagement := {
+ pDU_NAS_EPS_TrackingAreaUpdateComplete := {
+ securityHeaderType := securityHeaderType,
+ messageType := '01001010'B
+ }
+ }
+ }
+}
+
/* 8.2.28 Tracking Area Update Reject */
template (present) PDU_NAS_EPS
tr_PDU_NAS_EPS_TrackingAreaUpdateReject(template (present) EMM_CauseV cause := ?) := {
@@ -429,7 +469,9 @@
template (value) PDU_NAS_EPS
ts_PDU_NAS_EPS_TrackingAreaUpdateRequest(template (value) EPS_MobileIdentityLV old_guti,
template (omit) P_TMSISignatureTV old_ptmsi_sig := omit,
- template (omit) GUTI_TypeTV old_guti_type := omit) := {
+ template (omit) GUTI_TypeTV old_guti_type := omit,
+ template (omit) NonceTV nonce_ue := omit,
+ template (omit) CipheringKeySequenceNumberTV gprs_cksn := omit) := {
protocolDiscriminator := c_EPS_NAS_PD_EMM,
ePS_messages := {
ePS_MobilityManagement := {
@@ -440,10 +482,10 @@
nasKeySetId := ts_NAS_KeySetIdentifierV,
oldGUTI := old_guti,
nonCurrentNative_nasKeySetId := omit,
- gprsCipheringKeySequenceNumber := omit,
+ gprsCipheringKeySequenceNumber := gprs_cksn,
old_P_TMSISignature := old_ptmsi_sig,
additionalGUTI := omit,
- nonce := omit,
+ nonce := nonce_ue,
uENetworkCapability := omit,
lastVisitedRegisteredTAI := omit,
dRXParameter := omit,
diff --git a/library/S1AP_Emulation.ttcn b/library/S1AP_Emulation.ttcn
index e3e3216..955c690 100644
--- a/library/S1AP_Emulation.ttcn
+++ b/library/S1AP_Emulation.ttcn
@@ -72,7 +72,8 @@
};
type union S1APEM_Config {
NAS_Keys set_nas_keys,
- ResetNAScounts reset_nas_counts
+ ResetNAScounts reset_nas_counts,
+ NAS_ALG_INT set_nas_alg_int
};
type enumerated S1APEM_EventUpDown {
@@ -453,6 +454,11 @@
S1apAssociationTable[assoc_id].nus.rx_count := 0;
S1apAssociationTable[assoc_id].nus.tx_count := 0;
}
+ /* Configuration primitive from client */
+ [] S1AP_CLIENT.receive(S1APEM_Config:{set_nas_alg_int:=?}) -> value s1cfg sender vc_conn {
+ var integer assoc_id := f_assoc_id_by_comp(vc_conn);
+ S1apAssociationTable[assoc_id].nus.alg_int := s1cfg.set_nas_alg_int;
+ }
/* S1AP from client: InitialUE */
[] S1AP_CLIENT.receive(tr_S1AP_InitialUE) -> value msg sender vc_conn {
/* create a table entry about this connection */
diff --git a/mme/MME_Tests.ttcn b/mme/MME_Tests.ttcn
index 2194e8a..aa23a84 100644
--- a/mme/MME_Tests.ttcn
+++ b/mme/MME_Tests.ttcn
@@ -617,7 +617,7 @@
}
-private altstep as_s1ap_handle_IntialCtxSetupReq() runs on ConnHdlr {
+private altstep as_s1ap_handle_IntialCtxSetupReq_Attach_Accept() runs on ConnHdlr {
var S1AP_PDU rx_msg;
var PDU_NAS_EPS rx_nas;
[] S1AP.receive(tr_S1AP_IntialCtxSetupReq) -> value rx_msg {
@@ -654,6 +654,40 @@
}
}
+private altstep as_s1ap_handle_IntialCtxSetupReq_TAU_Accept() runs on ConnHdlr {
+ var S1AP_PDU rx_msg;
+ var PDU_NAS_EPS rx_nas;
+ [] S1AP.receive(tr_S1AP_IntialCtxSetupReq) -> value rx_msg {
+ /* 3GPP TS 23.401 D.3.6 step 22: */
+ var template (omit) MME_UE_S1AP_ID mme_ue_id := f_S1AP_get_MME_UE_S1AP_ID(rx_msg);
+ var template (omit) ENB_UE_S1AP_ID enb_ue_id := f_S1AP_get_ENB_UE_S1AP_ID(rx_msg);
+ var template (value) E_RABSetupItemCtxtSURes rab_setup_it;
+ var template (value) E_RABSetupListCtxtSURes rab_setup_items;
+ var S1APEM_Config cfg;
+
+ S1AP.receive(tr_PDU_NAS_EPS_TrackingAreaUpdateAccept)-> value rx_nas;
+
+ /* Configure integrity protection: */
+ cfg := {
+ set_nas_alg_int := NAS_ALG_IP_EIA1
+ };
+ S1AP.send(cfg);
+
+ rab_setup_it := ts_S1AP_RABSetupItemCtxtSURes(rab_id := 5,
+ tla := oct2bit(f_inet_addr(mp_mme_ip)),
+ gtp_teid := '00000002'O);
+ rab_setup_items := ts_S1AP_RABSetupListCtxtSURes(rab_setup_it);
+ S1AP.send(ts_S1AP_InitialCtxSetupResp(valueof(mme_ue_id), valueof(enb_ue_id), rab_setup_items));
+
+ /* 3GPP TS 23.401 D.3.6 step 23: */
+ /* Integrity Protection: TS 24.301 Section 4.4.4.3*/
+ S1AP.send(ts_PDU_NAS_EPS_TrackingAreaUpdateComplete(c_EPS_SEC_IP));
+ }
+ [] S1AP.receive(PDU_NAS_EPS:?) -> value rx_nas {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Rx Unexpected NAS PDU msg: ", rx_nas));
+ }
+}
+
private altstep as_s1ap_handle_UeContextReleaseCmd(template S1AP_IEs.Cause cause := ?) runs on ConnHdlr {
var S1AP_PDU rx_msg;
var PDU_NAS_EPS rx_nas;
@@ -925,6 +959,43 @@
}
+private altstep as_gtp_sgsn_context_2g_to_4g(OCT4 new_sgsn_teid := 'ABABABAB'O, GTP_Templates.GTP_RATType rat_type := GTP_RAT_TYPE_EUTRAN) runs on ConnHdlr {
+ var Gtp1cUnitdata gtpc_pdu;
+
+ [] GTP.receive(tr_GTPC_SGSNContextReq(g_gn_iface_peer, tr_SGSNContextReqPDU(rat_type := int2oct(enum2int(rat_type), 1)))) -> value gtpc_pdu {
+ var template (value) PDP_Context_GTPC pdp_ctx;
+ var template (value) GTPC_PDUs SGSNContextRespPDU;
+ var Gtp1cUnitdata gtpc_pdu_ack;
+ var OCT4 old_mme_remote_teid := gtpc_pdu.gtpc.gtpc_pdu.sgsn_ContextRequest.teidControlPlane.teidControlPlane;
+
+ const OCT16 ck := '740d62df9803eebde5120acf358433d0'O;
+ const OCT16 ik := '11329aae8e8d2941bb226b2061137c58'O;
+
+ pdp_ctx := ts_PDP_Context_GTPC(f_inet_addr(g_pars.ue_pars.ue_ip),
+ f_inet_addr(mp_gn_local_ip),
+ c_NAS_defaultAPN,
+ ggsn_teic := '12345678'O,
+ ggsn_teid := '87654321'O);
+ SGSNContextRespPDU := ts_SGSNContextRespPDU(GTP_CAUSE_REQUEST_ACCEPTED,
+ g_pars.ue_pars.imsi,
+ new_sgsn_teid,
+ f_inet_addr(mp_gn_local_ip),
+ ts_MM_ContextUMTS(ck, ik),
+ { pdp_ctx });
+ GTP.send(ts_GTPC_SGSNContextResp(g_gn_iface_peer,
+ old_mme_remote_teid,
+ oct2int(gtpc_pdu.gtpc.opt_part.sequenceNumber),
+ SGSNContextRespPDU));
+
+ GTP.receive(tr_GTPC_SGSNContextAck(g_gn_iface_peer, new_sgsn_teid,
+ tr_SGSNContextAckPDU(GTP_CAUSE_REQUEST_ACCEPTED))) -> value gtpc_pdu;
+ setverdict(pass);
+ }
+ [] GTP.receive {
+ setverdict(fail, "unexpected GTPC message from MME");
+ }
+}
+
private function f_attach() runs on ConnHdlr {
var template (value) EPS_MobileIdentityV mi := ts_NAS_MobileId_IMSI(g_pars.ue_pars.imsi);
var template (value) PDU_NAS_EPS nas_esm, nas_emm;
@@ -963,7 +1034,7 @@
T.start;
alt {
- [] as_s1ap_handle_IntialCtxSetupReq();
+ [] as_s1ap_handle_IntialCtxSetupReq_Attach_Accept();
[] T.timeout { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No message from MME")); }
}
@@ -1383,6 +1454,109 @@
vc_conn.done;
}
+/* 3GPP TS 23.401 D.3.6, TS 23.003 2.8.2.2 */
+private function rai_ptmsi2_guti(in RoutingAreaIdentity rai, in OCT4 ptmsi, in OCT3 ptmsi_sig, out NAS_EPS_Types.GUTI guti) runs on ConnHdlr {
+
+
+ var bitstring ptmsi_bits := oct2bit(ptmsi);
+ var bitstring ptmsi_sig_bits := oct2bit(ptmsi_sig);
+ var bitstring mtmsi_bits := '11'B &
+ substr(ptmsi_bits, 2, 6) &
+ substr(ptmsi_sig_bits, 0, 8) &
+ substr(ptmsi_bits, 16, 16);
+ guti := valueof(ts_NAS_GUTI(mcc_mnc := rai.mcc_digits & rai.mnc_digits,
+ mmegi := rai.lac,
+ mmec := rai.rac,
+ tmsi := bit2oct(mtmsi_bits)));
+}
+/* Test UE attached to GERAN reselecting a EUTRAN cell. In this scenario, the
+ * new MME will attempt to obtain information of the UE from the old SGSN
+ * through Gn interface using SGSN Context Request/Response procedure (OS#6294). */
+/* 3GPP TS 23.401 D.3.6, TS 23.003 2.8.2.1 */
+private function f_TC_ue_cell_reselect_geran_to_eutran(ConnHdlrPars pars) runs on ConnHdlr {
+ f_init_handler(pars);
+ f_gtp_register_imsi(g_pars.ue_pars.imsi);
+ f_gtp2_register_imsi(g_pars.ue_pars.imsi);
+ /* SGSN Context Req doesn't necessarily contain IMSI, hence expect it through TEID=0 */
+ f_gtp_register_teid('00000000'O);
+ /* passed in SGSN Context Resp to MME, will be used by MME when answering with SGSN Context Ack: */
+ const OCT4 new_sgsn_teid := 'ABABABAB'O;
+ f_gtp_register_teid(new_sgsn_teid);
+
+ var template (value) EPS_MobileIdentityV mi := ts_NAS_MobileId_IMSI(pars.ue_pars.imsi);
+ var template (value) S1AP_PDU tx;
+ var template (value) PDU_NAS_EPS nas_tau;
+ var RoutingAreaIdentity rai;
+ var OCT4 ptmsi := f_gen_tmsi(suffix := 0, nri_v := 0, nri_bitlen := 8);
+ var OCT3 ptmsi_sig := f_rnd_octstring(3);
+ var NAS_EPS_Types.GUTI guti_val;
+ var template (value) EPS_MobileIdentityLV old_guti;
+ var S1APEM_Config cfg;
+ timer T := 5.0;
+
+ rai := valueof(ts_RoutingAreaIdentity(mp_gn_local_mcc, mp_gn_local_mnc,
+ int2oct(mp_gn_local_lac, 2), int2oct(mp_gn_local_rac, 1)));
+ rai_ptmsi2_guti(rai, ptmsi, ptmsi_sig, guti_val);
+ old_guti := ts_EPS_MobileId_GUTI_(guti_val);
+
+ nas_tau := ts_PDU_NAS_EPS_TrackingAreaUpdateRequest(old_guti,
+ ts_PTMSI_SignatureTV(ptmsi_sig),
+ ts_GUTI_TypeTV(GUTI_TYPE_MAPPED),
+ ts_NonceTV('12345678'O),
+ ts_CipheringKeySequenceNumberTV('000'B));
+ tx := ts_S1AP_InitialUE(p_eNB_value := 0, p_nasPdu := enc_PDU_NAS_EPS(valueof(nas_tau)),
+ p_tAI := ts_enb_S1AP_TAI(g_pars.enb_pars[g_pars.mme_idx]),
+ p_eUTRAN_CGI := ts_enb_S1AP_CGI(g_pars.enb_pars[g_pars.mme_idx]),
+ p_rrcCause := mo_Signalling);
+
+ S1AP.send(tx);
+
+ /* NAS counts are reset to zero when a mapped security context is created. */
+ cfg := {
+ reset_nas_counts := {}
+ };
+ S1AP.send(cfg);
+
+ as_gtp_sgsn_context_2g_to_4g(new_sgsn_teid);
+
+ /* We now expect the MME to send a Create Session Request to the SGW-C */
+ T.start;
+ alt {
+ [] as_GTP2C_CreateSession_success();
+ [] T.timeout { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No message from MME")); }
+ }
+
+ /* 3GPP TS 23.401 D.3.6 steps 14-21: */
+ as_DIA_UpdLoc();
+
+ /* 3GPP TS 23.401 D.3.6 step 22, 23: */
+ as_s1ap_handle_IntialCtxSetupReq_TAU_Accept();
+
+ /* We now expect the MME to send a Modify Bearer Request to the SGW-C */
+ T.start;
+ alt {
+ [] as_GTP2C_ModifyBearer_success();
+ [] T.timeout { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No message from MME")); }
+ }
+
+ /* Leave some time for MME to handle Modify Bearer Response: */
+ f_sleep(1.0);
+}
+testcase TC_ue_cell_reselect_geran_to_eutran() runs on MTC_CT {
+ var charstring id := testcasename();
+
+ f_init_diameter(id);
+ f_init_s1ap(id, 7);
+ f_init_gtpv2_s11(id);
+ f_s1ap_setup(0);
+ f_init_gtp(id);
+
+ var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
+ var ConnHdlr vc_conn;
+ vc_conn := f_start_handler_with_pars(refers(f_TC_ue_cell_reselect_geran_to_eutran), pars);
+ vc_conn.done;
+}
+
control {
execute( TC_s1ap_setup_wrong_plmn() );
execute( TC_s1ap_setup_wrong_tac() );
@@ -1393,6 +1567,7 @@
execute( TC_RIM_RAN_INF() );
execute( TC_s1ap_reset() );
execute( TC_ue_cell_reselect_eutran_to_geran() );
+ execute( TC_ue_cell_reselect_geran_to_eutran() );
}