mme: Introduce test TC_ue_cell_reselect_eutran_to_geran
Initial bits to be able to test SGSN Context Request+Response emulating
an UE doing cell reselection from 4G to 2G.
Related: OS#6294
Change-Id: I707cb8c6b39c1440db5ccc2f02d08337b38fb564
diff --git a/library/GTP_Templates.ttcn b/library/GTP_Templates.ttcn
index 06ba208..839ed28 100644
--- a/library/GTP_Templates.ttcn
+++ b/library/GTP_Templates.ttcn
@@ -41,6 +41,37 @@
/* FIXME */
};
+ template (value) Cause_gtpc ts_Cause_gtpc(template (value) GTP_Cause cause) := {
+ type_gtpc := '01'O,
+ causevalue := enum2oct1_Cause_gtpc_tmpl(cause)
+ }
+ private function enum2oct1_Cause_gtpc_tmpl(template GTP_Cause inp) return template OCT1
+ {
+ if (istemplatekind(inp, "omit")) {
+ return omit;
+ } else if (istemplatekind(inp, "*")) {
+ return *;
+ } else if (istemplatekind(inp, "?")) {
+ return ?;
+ } else {
+ return int2oct(enum2int(valueof(inp)), 1);
+ }
+ }
+ template (present) Cause_gtpc tr_Cause_gtpc(template (present) GTP_Cause cause) := {
+ type_gtpc := '01'O,
+ causevalue := enum2oct1_Cause_gtpc_tmpl(cause)
+ }
+ function f_tr_Cause_gtpc(template GTP_Cause cause) return
+ template Cause_gtpc {
+ if (istemplatekind(cause, "omit")) {
+ return omit;
+ } else if (istemplatekind(cause, "*")) {
+ return *;
+ } else {
+ return tr_Cause_gtpc(cause);
+ }
+ }
+
private function f_oct_or_wc(template integer inp, integer len) return template octetstring {
if (istemplatekind(inp, "omit")) {
return omit;
@@ -119,6 +150,18 @@
restartCounter := restart_counter
}
+ /* Packet TMSI - 7.7.5 */
+ template (value) PacketTMSI ts_PTMSI(OCT4 ptmsi) := {
+ type_gtpc := '05'O,
+ p_tmsi := ptmsi
+ }
+
+ /* PTMSI Signature - 7.7.9 */
+ template (value) PTMSI_Signature ts_PTMSI_sig(OCT3 ptmsi_sig) := {
+ type_gtpc := '0C'O,
+ ptmsi_Signature := ptmsi_sig
+ }
+
/* IMEI(SV) IE TS 29.060 7.7.53 */
template (value) IMEISV_gtpc ts_IMEISV(template (value) OCT8 imeisv) := {
type_gtpc := '9A'O,
@@ -350,7 +393,7 @@
apn_value := apn
}
- template (value) GSN_Address_GTPC ts_GsnAddr(octetstring ip_addr) := {
+ template (value) GSN_Address_GTPC ts_GsnAddr(template (value) octetstring ip_addr) := {
type_gtpc := '85'O,
lengthf := lengthof(ip_addr),
addressf := ip_addr
@@ -402,6 +445,29 @@
digits := digits,
padding := 'F'H
}
+ function f_ts_Imsi(template (omit) hexstring digits := omit) return template (omit) IMSI_gtpc {
+ var template (omit) IMSI_gtpc imsi;
+ if (istemplatekind(digits, "omit")) {
+ imsi := omit;
+ } else {
+ imsi := ts_Imsi(valueof(digits));
+ }
+ return imsi;
+ }
+ template (present) IMSI_gtpc tr_Imsi(template (present) hexstring digits) := {
+ type_gtpc := '02'O,
+ digits := digits,
+ padding := 'F'H
+ }
+ function f_tr_Imsi(template hexstring digits := *) return template IMSI_gtpc {
+ if (istemplatekind(digits, "omit")) {
+ return omit;
+ } else if (istemplatekind(digits, "*")) {
+ return *;
+ } else {
+ return tr_Imsi(digits);
+ }
+ }
function f_ts_RATType(template (omit) OCT1 ratType := omit) return template (omit) RATType {
var template (omit) RATType rt;
@@ -417,6 +483,17 @@
return rt;
}
+ template (value) RoutingAreaIdentity ts_RoutingAreaIdentity(template (value) hexstring mcc_digits,
+ template (value) hexstring mnc_digits,
+ template (value) OCT2 lac,
+ template (value) OCT1 rac) := {
+ type_gtpc := '03'O,
+ mcc_digits := mcc_digits,
+ mnc_digits := mnc_digits,
+ lac := lac,
+ rac := rac
+ }
+
template (value) GeographicLocationCGI
ts_GeographicLocationCGI(template (value) hexstring mcc,
template (value) hexstring mnc,
@@ -869,6 +946,101 @@
valueof(ts_DeletePdpRespPDU(cause, pco)), seq)
}
+ /* SGSN Context Request - 7.5.3 */
+ template (value) GTPC_PDUs ts_SGSNContextReqPDU(template (value) RoutingAreaIdentity rai,
+ template (value) OCT4 teic,
+ template (value) octetstring sgsn_addr_control,
+ template (omit) hexstring imsi := omit,
+ template (value) BIT1 msValidated := '0'B,
+ template (omit) TLLI tlli := omit,
+ template (omit) PacketTMSI ptmsi := omit,
+ template (omit) PTMSI_Signature ptmsi_sig := omit,
+ template (omit) OCT1 rat_type := omit) := {
+ sgsn_ContextRequest := {
+ imsi := f_ts_Imsi(imsi),
+ routingAreaIdentity := rai,
+ tlli := tlli,
+ packetTMSI := ptmsi,
+ ptmsi_Signature := ptmsi_sig,
+ ms_Validated := {
+ type_gtpc := '0D'O,
+ msValidated := msValidated,
+ spare := '1111111'B
+ },
+ teidControlPlane := {
+ type_gtpc := '11'O,
+ teidControlPlane := teic
+ },
+ sgsn_addr_controlPlane := ts_GsnAddr(sgsn_addr_control),
+ alternative_sgsn_addr_controlPlane := omit,
+ sGSN_Number := omit,
+ ratType := f_ts_RATType(rat_type),
+ hopCounter := omit,
+ private_extension_gtpc := omit
+ }
+ }
+ template (value) Gtp1cUnitdata ts_GTPC_SGSNContextReq(GtpPeer peer, uint16_t seq,
+ template (value) GTPC_PDUs SGSNContextReqPDU) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(sgsnContextRequest, '00000000'O, valueof(SGSNContextReqPDU), seq)
+ }
+
+ /* SGSN Context Response - 7.5.4 */
+ template (present) GTPC_PDUs tr_SGSNContextRespPDU(template (present) GTP_Cause cause := ?,
+ template hexstring imsi := *) := {
+ sgsn_ContextResponse := {
+ cause := tr_Cause_gtpc(cause),
+ imsi := f_tr_Imsi(imsi),
+ teidControlPlane := *,
+ rabContext := *,
+ radioPrioritySMS := *,
+ radioPriority := *,
+ packetFlowID := *,
+ charging_char := *,
+ mm_Context := *,
+ pdp_Context := *,
+ sgsn_addr_controlPlane := *,
+ pdpContextPriorization := *,
+ radioPriority_LCS := *,
+ mBMS_UE_Context := *,
+ subscribedRFSP_Index := *,
+ rFSP_IndexInUse := *,
+ colocatedGGSN_PGW_FQDN := *,
+ evolvedAllocationRetentionPriorityII := *,
+ extendedCommonFlags := *,
+ ue_network_capability := *,
+ ue_ambr := *,
+ apn_ambr_nsapi := *,
+ signallingPriorityIndication_nsapi := *,
+ higher_bitrates_than_16mbps_flag := *,
+ selectionMode_nsapi := *,
+ localHomeNetworkID_nsapi := *,
+ uE_UsageType := *,
+ extendedCommonFlagsII := *,
+ private_extension_gtpc := *
+ }
+ }
+ template (present) Gtp1cUnitdata tr_GTPC_SGSNContextResp(template (present) GtpPeer peer := ?,
+ template (present) OCT4 teid := ?,
+ template (present) GTPC_PDUs SGSNContextRespPDU := ?)
+ := tr_GTPC_MsgType(peer, sgsnContextResponse, teid, SGSNContextRespPDU);
+
+ /* SGSN Context Acknowledge - 7.5.5 */
+ template (value) GTPC_PDUs ts_SGSNContextAckPDU(template (value) GTP_Cause cause := GTP_CAUSE_REQUEST_ACCEPTED) := {
+ sgsn_ContextAcknowledge := {
+ cause := ts_Cause_gtpc(cause),
+ teidDataII := omit,
+ sgsn_AddressForUserTraffic := omit,
+ sgsn_Number := omit,
+ nodeIdentifier := omit,
+ private_extension_gtpc := omit
+ }
+ }
+ template (value) Gtp1cUnitdata ts_GTPC_SGSNContextAck(GtpPeer peer, uint16_t seq,
+ template (value) GTPC_PDUs SGSNContextAckPDU := ts_SGSNContextAckPDU(GTP_CAUSE_REQUEST_ACCEPTED)) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(sgsnContextAcknowledge, '00000000'O, valueof(SGSNContextAckPDU), seq)
+ }
/* GTP-C RIM */
diff --git a/mme/MME_Tests.ttcn b/mme/MME_Tests.ttcn
index eca6b04..f43bfbd 100644
--- a/mme/MME_Tests.ttcn
+++ b/mme/MME_Tests.ttcn
@@ -81,6 +81,7 @@
type record UeParams {
hexstring imsi,
charstring ue_ip,
+ NAS_EPS_Types.GUTI guti optional,
/* TEI (Control) local side, S11 (SGW) */
OCT4 s11_teic_local,
@@ -277,6 +278,7 @@
uep := {
imsi := f_gen_imsi(imsi_suffix),
ue_ip := "192.168.123.50",
+ guti := omit,
s11_teic_local := '00000000'O,
s11_teic_remote := omit,
s5c_teic_local := '00000000'O,
@@ -613,6 +615,14 @@
var template (value) E_RABSetupListCtxtSURes rab_setup_items;
var octetstring esm_enc;
var template (value) PDU_NAS_EPS nas;
+ var EPS_MobileIdentityTLV mi_tlv;
+
+ S1AP.receive(tr_NAS_AttachAccept()) -> value rx_nas;
+ mi_tlv := rx_nas.ePS_messages.ePS_MobilityManagement.pDU_NAS_EPS_AttachAccept.gUTI;
+ if (mi_tlv.ePS_MobileIdentity.ePS_MobileIdentity.typeOfIdentity != '110'B) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Rx GUTI of unexpected MI type: ", mi_tlv));
+ }
+ g_pars.ue_pars.guti := mi_tlv.ePS_MobileIdentity.ePS_MobileIdentity.oddEvenInd_identity.guti
rab_setup_it := ts_S1AP_RABSetupItemCtxtSURes(rab_id := 5,
tla := oct2bit(f_inet_addr(mp_mme_ip)),
@@ -1186,6 +1196,91 @@
vc_conn.done;
}
+/* Test UE attached to EUTRAN reselecting a GERAN cell. In this scenario, the
+ * new SGSN will attempt to obtain information of the UE from the old SGSN (MME)
+ * through Gn interface using SGSN Context Request/Response procedure (OS#6294). */
+/* TS 23.003 2.8.2.1 */
+private function guti2rai_ptmsi(in NAS_EPS_Types.GUTI guti, out RoutingAreaIdentity rai, out OCT4 ptmsi, out OCT3 ptmsi_sig) runs on ConnHdlr {
+ var bitstring mtmsi_bits := oct2bit(guti.mTMSI);
+ var bitstring ptmsi_bits;
+ var bitstring ptmsi_sig_bits;
+
+ rai := valueof(ts_RoutingAreaIdentity(guti.mccDigit1 & guti.mccDigit2 & guti.mccDigit3,
+ guti.mncDigit3 & guti.mncDigit1 & guti.mncDigit2,
+ guti.mMEGI, guti.mMEC));
+ /* 3GPP TS 23.003 2.8.2.0: "P-TMSI shall be of 32 bits length where the two topmost bits are
+ * reserved and always set to '11'. Hence, for a UE which may handover to GERAN/UTRAN (based on
+ * subscription and UE capabilities), the corresponding bits in the M-TMSI are set to '11'"
+ */
+ ptmsi_bits := '11'B & substr(mtmsi_bits, 2, 6) & oct2bit(guti.mMEC) & substr(mtmsi_bits, 16, 16);
+ ptmsi_sig_bits := substr(mtmsi_bits, 8, 8) & oct2bit('0000'O);
+ ptmsi := bit2oct(ptmsi_bits);
+ ptmsi_sig := bit2oct(ptmsi_sig_bits);
+ /* TODO: The UE shall fill the remaining 2 octets of the <P-TMSI signature> according to clauses 9.1.1, 9.4.1, 10.2.1, or
+ * 10.5.1 of 3GPP TS.33.401 [89] , as appropriate, for RAU/Attach procedures.*/
+ /* TODO: 3GPP TS 33.401 9.1.1 The 16 least significant bits available in
+ * the P-TMSI signature field shall be filled with the truncated NAS-token
+ * according to 3GPP TS 23.003 [3].The truncated NAS-token is defined as the 16
+ * least significant bits of the NAS-token.
+ * The NAS-token is derived as specified in Annex A.9. The UE shall use the uplink NAS COUNT value that it would use
+ * in the next NAS message to calculate the NAS-token and increase the stored uplink NAS COUNT value by 1.*/
+ /* TODO: mMEC "also copied into the 8 Most Significant Bits of the NRI field within the P-TMSI" */
+}
+private function f_TC_ue_cell_reselect_eutran_to_geran(ConnHdlrPars pars) runs on ConnHdlr {
+ var template (value) GTPC_PDUs SGSNContextReqPDU;
+ var RoutingAreaIdentity rai;
+ var OCT4 ptmsi;
+ var OCT3 ptmsi_sig;
+ var Gtp1cUnitdata gtpc_pdu;
+
+ f_init_handler(pars);
+ f_gtp_register_imsi(g_pars.ue_pars.imsi);
+ f_attach();
+
+ /* TODO: take GUTI from as_s1ap_handle_IntialCtxSetupReq() in g_pars,
+ * convert it to P-TMSI and pass P-TMSI below */
+ guti2rai_ptmsi(g_pars.ue_pars.guti, rai, ptmsi, ptmsi_sig);
+
+ SGSNContextReqPDU := ts_SGSNContextReqPDU(rai, '00000000'O, f_inet_addr(mp_gn_local_ip),
+ ptmsi := ts_PTMSI(ptmsi), ptmsi_sig := ts_PTMSI_sig(ptmsi_sig));
+ GTP.send(ts_GTPC_SGSNContextReq(g_gn_iface_peer, 0, SGSNContextReqPDU));
+
+ timer T := 5.0;
+ T.start;
+ alt {
+ [] GTP.receive(tr_GTPC_SGSNContextResp(g_gn_iface_peer, '00000000'O,
+ tr_SGSNContextRespPDU(GTP_CAUSE_REQUEST_ACCEPTED,
+ g_pars.ue_pars.imsi))) -> value gtpc_pdu {
+ setverdict(pass);
+ }
+ [] GTP.receive {
+ setverdict(fail, "unexpected GTPC message from MME");
+ }
+ [] T.timeout {
+ setverdict(fail, "no SGSN Context Response from MME");
+ }
+ }
+
+ GTP.send(ts_GTPC_SGSNContextAck(g_gn_iface_peer, oct2int(gtpc_pdu.gtpc.opt_part.sequenceNumber),
+ ts_SGSNContextAckPDU(GTP_CAUSE_REQUEST_ACCEPTED)));
+ /* Give some time to process the SGSNContextACK: */
+ f_sleep(3.0);
+}
+testcase TC_ue_cell_reselect_eutran_to_geran() runs on MTC_CT {
+ var charstring id := testcasename();
+
+ f_init_diameter(id);
+ f_init_s1ap(id, 4);
+ 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_eutran_to_geran), pars);
+ vc_conn.done;
+}
+
control {
execute( TC_s1ap_setup_wrong_plmn() );
execute( TC_s1ap_setup_wrong_tac() );
@@ -1195,6 +1290,7 @@
execute( TC_gn_echo_request() );
execute( TC_RIM_RAN_INF() );
execute( TC_s1ap_reset() );
+ execute( TC_ue_cell_reselect_eutran_to_geran() );
}