mme: Implement missing UE attach steps
Related: OS#6294
Change-Id: Ib4a69aef40bf9dd17d640f650e459668f8415aaa
diff --git a/library/GTPv2_Templates.ttcn b/library/GTPv2_Templates.ttcn
index 1ccbcb8..c09bca8 100644
--- a/library/GTPv2_Templates.ttcn
+++ b/library/GTPv2_Templates.ttcn
@@ -1040,6 +1040,65 @@
privateExtension := omit
}});
+template (present) PDU_GTPCv2
+tr_GTP2C_ModifyBearerReq(template (present) OCT4 d_teid := ?,
+ template (present) OCT3 seq := ?) :=
+tr_PDU_GTP2C(d_teid, seq, {
+ modifyBearerRequest := {
+ mEI := *,
+ userLocationInfo := *,
+ servingNetwork := *,
+ rAT_Type := *,
+ indicationFlags := *,
+ fullyQualifiedTEID := *,
+ ambr := *,
+ delayDownlinkPacketNotificationReq := *,
+ bearerContextGrouped := *,
+ recovery := *,
+ uE_TimeZone := *,
+ csid := *,
+ user_CSG_Information := *,
+ iP_Addr := *,
+ portNumber := *,
+ lDN := *,
+ //maxMBR_APN_AMBR := *,
+ cNOperatorSelectionEntity := *,
+ presenceReportingAreaInformation := *,
+ overloadControlInformationGrouped := *,
+ servingPLMNRateControl := *,
+ counter := *,
+ privateExtension := *
+ }});
+
+template (value) PDU_GTPCv2
+ts_GTP2C_ModifyBearerResp(template (value) OCT4 d_teid,
+ template (value) OCT3 seq,
+ template (value) GTP2C_Cause cause,
+ template (value) uint4_t bearer_id,
+ template (omit) BearerContextGrouped_List bearerContextGrouped := omit) :=
+ts_PDU_GTP2C(d_teid, seq, '23'O, {
+ modifyBearerResponse := {
+ cause := ts_GTP2C_Cause(cause, '0'B),
+ mSISDN := omit,
+ linkedEPS_Bearer_ID := ts_GTP2C_EpsBearerId(bearer_id),
+ aPN_Restriction := omit,
+ protocolConfigOptions := omit,
+ bearerContextGrouped := bearerContextGrouped,
+ changeReportingAction := omit,
+ cSG_InformationReportingAction := omit,
+ heNBInformationReporting := omit,
+ chargingGatewayName := omit,
+ chargingGatewayAddress := omit,
+ csid := omit,
+ recovery := omit,
+ lDN := omit,
+ indicationFlags := omit,
+ presenceReportingAreaAction := omit,
+ loadControlInformationGrouped := omit,
+ overloadControlInformationGrouped := omit,
+ pDNConnectionChargingID := omit,
+ privateExtension := omit
+ }});
template (value) PDU_GTPCv2
ts_GTP2C_DeleteBearerReq(template (value) OCT4 d_teid,
diff --git a/library/NAS_Templates.ttcn b/library/NAS_Templates.ttcn
index 45f5f8d..70561b3 100644
--- a/library/NAS_Templates.ttcn
+++ b/library/NAS_Templates.ttcn
@@ -1025,6 +1025,55 @@
}
}
}
+template (present) PDU_NAS_EPS
+tr_NAS_ActDefEpsBearCtxReq(template (present) BIT4 bearer_id := ?,
+ template (present) BIT8 proc_tid := ?,
+ template (present) EPS_QualityOfServiceV qos := ?,
+ template (present) octetstring apn := ?,
+ template (present) BIT3 addr_type := ?,
+ template (present) octetstring addr_info := ?) := {
+ protocolDiscriminator := c_EPS_NAS_PD_ESM,
+ ePS_messages := {
+ ePS_SessionManagement := {
+ pDU_NAS_EPS_ActDefEPSBearerContextRequest := {
+ ePSBearerIdentity := bearer_id,
+ procedureTransactionIdentifier := proc_tid,
+ messageType := '11000001'B,
+ ePS_QoS := {
+ lengthIndicator := ?,
+ ePS_QualityOfServiceV := qos
+ },
+ accessPointName := {
+ lengthIndicator := 0,
+ accessPointNameValue := apn
+ },
+ pDN_Address := {
+ lengthIndicator := 0,
+ typeValue := addr_type,
+ spare := '00000'B,
+ addressInformation := addr_info
+ },
+ transactionIdentifier := *,
+ negotiatedQoS := *,
+ negotiated_LLC_SAPI := *,
+ radioPriority := *,
+ packetFlowID := *,
+ aPN_AMBR := *,
+ esmCause := *,
+ protocolConfigOptions := *,
+ connectivityType := *,
+ wLANOffloadIndication := *,
+ nBIFOMContainer := *,
+ headerCompressinConfiguration := *,
+ controlPlaneOnlyIndication := *,
+ extendedProtocolConfigurationOptions := *,
+ servingPLMNRateControl := *,
+ extended_APN_AMBR := *,
+ extendedQoS := *
+ }
+ }
+ }
+}
/* 8.3.4 Activate Default EPS Bearer Context Accept */
template (value) PDU_NAS_EPS
diff --git a/library/s1ap/S1AP_Templates.ttcn b/library/s1ap/S1AP_Templates.ttcn
index 9e75cec..26e1ae1 100644
--- a/library/s1ap/S1AP_Templates.ttcn
+++ b/library/s1ap/S1AP_Templates.ttcn
@@ -22,7 +22,7 @@
*********************************************************************************/
/*********************************************************************************
- * 9.1.8 Management Messages
+ * 9.1.8 Management Messages
*********************************************************************************/
/* 9.1.8.4 S1 SETUP REQUEST */
@@ -578,11 +578,30 @@
}
/* 9.1.4.3 INITIAL CONTEXT SETUP RESPONSE */
+template (value) E_RABSetupItemCtxtSURes
+ts_S1AP_RABSetupItemCtxtSURes(template (value) E_RAB_ID rab_id := 5,
+ template (value) TransportLayerAddress tla := '00001010000101110001100000000100'B,
+ template (value) GTP_TEID gtp_teid := '00000002'O) := {
+ e_RAB_ID := rab_id,
+ transportLayerAddress := tla,
+ gTP_TEID := gtp_teid,
+ iE_Extensions := omit
+}
+template (value) E_RABSetupListCtxtSURes
+ts_S1AP_RABSetupListCtxtSURes(template (value) E_RABSetupItemCtxtSURes it := ts_S1AP_RABSetupItemCtxtSURes()) := {
+ {
+ id := S1AP_Constants.id_E_RABSetupItemCtxtSURes,
+ criticality := ignore,
+ value_ := { E_RABSetupItemCtxtSURes := it }
+ }
+}
+
template (value) S1AP_PDU
ts_S1AP_InitialCtxSetupResp(template (value) MME_UE_S1AP_ID mme_id,
template (value) ENB_UE_S1AP_ID enb_id,
- template (value) E_RABSetupListCtxtSURes rab_setup_items,
- template (value) E_RABList rab_items) := {
+ template (value) E_RABSetupListCtxtSURes rab_setup_items
+ /*OPTIONAL: template (value) E_RABList rab_items */
+ ) := {
successfulOutcome := {
procedureCode := id_InitialContextSetup,
criticality := reject,
@@ -598,14 +617,15 @@
criticality := reject,
value_ := {ENB_UE_S1AP_ID := enb_id}
}, {
- id := S1AP_Constants.id_E_RABSetupListBearerSURes,
+ id := S1AP_Constants.id_E_RABSetupListCtxtSURes,
criticality := ignore,
value_ := {E_RABSetupListCtxtSURes := rab_setup_items}
- }, {
+ }
+ /*, {
id := S1AP_Constants.id_E_RABFailedToSetupListBearerSURes,
criticality := ignore,
value_ := {E_RABList := rab_items}
- }
+ }*/
}
}
}
diff --git a/mme/MME_Tests.ttcn b/mme/MME_Tests.ttcn
index ce30279..eca6b04 100644
--- a/mme/MME_Tests.ttcn
+++ b/mme/MME_Tests.ttcn
@@ -13,6 +13,7 @@
import from General_Types all;
import from Native_Functions all;
import from IPL4asp_Types all;
+import from Misc_Helpers all;
import from S1AP_Types all;
import from S1AP_Templates all;
import from S1AP_Emulation all;
@@ -63,9 +64,34 @@
SupportedTAs supported_tas
}
+type record BearerConfig {
+ /* EPS Bearer ID */
+ uint4_t ebi optional,
+ /* TEI (Data) local side, S11 (SGW) */
+ OCT4 s11_teid_local optional,
+ /* TEI (Data) remote side, S11 (SGW) */
+ OCT4 s11_teid_remote optional,
+ /* TEI (Data) local side, S5c (PGW) */
+ OCT4 s5c_teid_local optional,
+ /* TEI (Data) remote side, S5c (PGW) */
+ OCT4 s5c_teid_remote optional
+};
+
/* parameters of emulated UE */
type record UeParams {
- hexstring imsi
+ hexstring imsi,
+ charstring ue_ip,
+
+ /* TEI (Control) local side, S11 (SGW) */
+ OCT4 s11_teic_local,
+ /* TEI (Control) remote side, S11 (SGW) */
+ OCT4 s11_teic_remote optional,
+ /* TEI (Control) local side, S5c (PGW) */
+ OCT4 s5c_teic_local,
+ /* TEI (Control) remote side, S5c (PGW) */
+ OCT4 s5c_teic_remote optional,
+
+ BearerConfig bearer optional
}
type component MTC_CT {
@@ -168,6 +194,9 @@
integer mp_s11_local_port := 2123;
charstring mp_s11_remote_ip := "127.0.0.2";
integer mp_s11_remote_port := 2123;
+
+ /* PGW information announced by SGWC. MME never really interacts with these. */
+ charstring mp_s5c_pgw_ip := "1.2.3.4";
}
/* send incoming unit data messages (like reset) to global SGsAP_UNIT port */
@@ -246,7 +275,19 @@
}
friend function f_init_one_ue(inout UeParams uep, integer imsi_suffix) {
uep := {
- imsi := f_gen_imsi(imsi_suffix)
+ imsi := f_gen_imsi(imsi_suffix),
+ ue_ip := "192.168.123.50",
+ s11_teic_local := '00000000'O,
+ s11_teic_remote := omit,
+ s5c_teic_local := '00000000'O,
+ s5c_teic_remote := omit,
+ bearer := {
+ ebi := omit,
+ s11_teid_local := omit,
+ s11_teid_remote := omit,
+ s5c_teid_local := omit,
+ s5c_teid_remote := omit
+ }
}
}
friend function f_init_s1ap(charstring id, integer imsi_suffix) runs on MTC_CT {
@@ -561,6 +602,33 @@
}
}
+
+private altstep as_s1ap_handle_IntialCtxSetupReq() runs on ConnHdlr {
+ var S1AP_PDU rx_msg;
+ var PDU_NAS_EPS rx_nas;
+ [] S1AP.receive(tr_S1AP_IntialCtxSetupReq) -> value rx_msg {
+ 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 octetstring esm_enc;
+ var template (value) PDU_NAS_EPS nas;
+
+ 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));
+
+ nas := ts_NAS_ActDefEpsBearCtxAck(int2bit(g_pars.ue_pars.bearer.ebi, 4), '00000000'B, omit);
+ esm_enc := enc_PDU_NAS_EPS(valueof(nas));
+ S1AP.send(ts_NAS_AttachComplete(esm_enc));
+ }
+ [] S1AP.receive(PDU_NAS_EPS:?) -> value rx_nas {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Rx Unexpected NAS PDU msg: ", rx_nas));
+ }
+}
+
/* Exepect AuthInfoReq (AIR) from HSS; respond with AuthInforAnswer (AIA) */
private altstep as_DIA_AuthInfo() runs on ConnHdlr {
var PDU_DIAMETER rx_dia;
@@ -616,18 +684,95 @@
}
}
-private function f_TC_attach(ConnHdlrPars pars) runs on ConnHdlr {
+private altstep as_GTP2C_CreateSession_success() runs on ConnHdlr {
+ var PDU_GTPCv2 rx_msg;
+ var BearerContextIEs rx_bctx_ies;
+ var template (value) FullyQualifiedTEID s11_fteid_c_ie, s11_fteid_u_ie, s5c_fteid_c_ie, s5c_fteid_u_ie;
+ var template (value) PDN_AddressAllocation paa;
+ var template (value) BearerContextIEs bctx_ies;
- f_init_handler(pars);
- var template (value) EPS_MobileIdentityV mi := ts_NAS_MobileId_IMSI(pars.ue_pars.imsi);
+ [] GTP2.receive(tr_GTP2C_CreateSessionReq(g_pars.ue_pars.imsi)) -> value rx_msg {
+ /* Parse TEIC and Bearer EBI and TEID and store it in g_pars */
+ g_pars.ue_pars.s11_teic_remote := rx_msg.gtpcv2_pdu.createSessionRequest.fullyQualifiedTEID[0].tEID_GRE_Key;
+ g_pars.ue_pars.s5c_teic_remote := rx_msg.gtpcv2_pdu.createSessionRequest.fullyQualifiedTEID[1].tEID_GRE_Key;
+
+ rx_bctx_ies := rx_msg.gtpcv2_pdu.createSessionRequest.bearerContextGrouped[0].bearerContextIEs;
+ g_pars.ue_pars.bearer.ebi := rx_bctx_ies.ePS_Bearer_ID.ePS_Bearer_ID_Value;
+
+ /* allocate + register TEID-C on local side */
+ g_pars.ue_pars.s11_teic_local := f_gtp2_allocate_teid();
+ g_pars.ue_pars.bearer.s11_teid_local := g_pars.ue_pars.s11_teic_local;
+ g_pars.ue_pars.s5c_teic_local := f_gtp2_allocate_teid();
+ g_pars.ue_pars.bearer.s5c_teid_local := g_pars.ue_pars.s5c_teic_local;
+
+ s11_fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S11_MME_GTPC, g_pars.ue_pars.s11_teic_local, 0,
+ f_inet_addr(mp_s11_local_ip), omit);
+ s5c_fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_PGW_GTPC, g_pars.ue_pars.s5c_teic_local, 1,
+ f_inet_addr(mp_s5c_pgw_ip), omit);
+ s11_fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S1U_SGW_GTPU, g_pars.ue_pars.bearer.s11_teid_local, 0,
+ f_inet_addr(mp_s11_local_ip), omit);
+ s5c_fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_PGW_GTPU, g_pars.ue_pars.bearer.s5c_teid_local, 2,
+ f_inet_addr(mp_s5c_pgw_ip), omit);
+ paa := ts_GTP2C_PdnAddrAlloc_v4(f_inet_addr(g_pars.ue_pars.ue_ip));
+ bctx_ies := ts_GTP2C_BcContextIE(ebi := g_pars.ue_pars.bearer.ebi,
+ teid_list := { s11_fteid_u_ie, s5c_fteid_u_ie },
+ qos := ts_GTP2C_BearerQos('09'O, 0, 0, 0, 0),
+ charging_id := ts_GTP2C_ChargingID(g_pars.ue_pars.bearer.s11_teid_local));
+
+ GTP2.send(ts_GTP2C_CreateSessionResp(g_pars.ue_pars.s11_teic_remote,
+ rx_msg.sequenceNumber,
+ { s11_fteid_c_ie, s5c_fteid_c_ie },
+ paa, { ts_GTP2C_BcGrouped(bctx_ies) } ));
+ setverdict(pass);
+ }
+ [] GTP2.receive {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected GTPv2/S11 message from MME"));
+ }
+}
+
+private altstep as_GTP2C_ModifyBearer_success() runs on ConnHdlr {
+ var PDU_GTPCv2 rx_msg;
+ var BearerContextIEs rx_bctx_ies;
+ var template (value) FullyQualifiedTEID s11_fteid_c_ie, s11_fteid_u_ie, s5c_fteid_c_ie, s5c_fteid_u_ie;
+ var template (value) BearerContextIEs bctx_ies;
+
+ [] GTP2.receive(tr_GTP2C_ModifyBearerReq(g_pars.ue_pars.s11_teic_local)) -> value rx_msg {
+
+ rx_bctx_ies := rx_msg.gtpcv2_pdu.modifyBearerRequest.bearerContextGrouped[0].bearerContextIEs;
+
+ /* TODO: validate the S1-U fullyQualifiedTEID announces the IP address provided by the ENB in InitialCtxSetupResp */
+ // rx_bctx_ies.fullyQualifiedTEID[0]. == f_inet_addr(mp_mme_ip)
+
+ /* Update S11 TEID */
+ g_pars.ue_pars.bearer.s11_teid_remote := rx_bctx_ies.fullyQualifiedTEID[0].tEID_GRE_Key;
+
+ s11_fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S1U_SGW_GTPU, g_pars.ue_pars.bearer.s11_teid_local, 0,
+ f_inet_addr(mp_s11_local_ip), omit);
+ bctx_ies := ts_GTP2C_BcContextIE(ebi := g_pars.ue_pars.bearer.ebi,
+ teid_list := { s11_fteid_u_ie },
+ qos := ts_GTP2C_BearerQos('09'O, 0, 0, 0, 0),
+ charging_id := ts_GTP2C_ChargingID(g_pars.ue_pars.bearer.s11_teid_local));
+
+ GTP2.send(ts_GTP2C_ModifyBearerResp(g_pars.ue_pars.s11_teic_remote,
+ rx_msg.sequenceNumber,
+ Request_accepted,
+ g_pars.ue_pars.bearer.ebi,
+ { ts_GTP2C_BcGrouped(bctx_ies) } ));
+ setverdict(pass);
+ }
+ [] GTP2.receive {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected GTPv2/S11 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;
timer T := 5.0;
-/*
- nas_esm := ts_NAS_ActDefEpsBearCtxReq(bearer_id := '0000'B, proc_tid := int2bit(1,8),
- qos := c_NAS_defaultQoS, apn := c_NAS_defaultAPN,
- addr_type := '000'B, addr_info := ''O);
-*/
nas_esm := ts_NAS_PdnConnReq(bearer_id := '0000'B, proc_tid := int2bit(1,8),
pdn_type := NAS_PDN_T_IPv4, req_type := '001'B);
nas_emm := ts_NAS_AttachRequest(att_type := '000'B, kset_id := '000'B, mobile_id := mi,
@@ -652,23 +797,31 @@
}
/* We now expect the MME to send a Create Session Request to the SGW-C */
- /* TODO: be more restrictive, fix and use tr_GTP2C_CreateSessionReq */
f_gtp2_register_udmsg('20'O);
T.start;
alt {
- [] GTP2.receive(tr_PDU_GTP2C) {
- setverdict(pass);
- }
- [] GTP2.receive {
- setverdict(fail, "unexpected GTPv2/S11 message from MME");
- }
- [] T.timeout {
- setverdict(fail, "no message from MME");
- }
+ [] as_GTP2C_CreateSession_success();
+ [] T.timeout { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No message from MME")); }
}
- /* TODO: Finish this procedure until Attach Complete */
+ T.start;
+ alt {
+ [] as_s1ap_handle_IntialCtxSetupReq();
+ [] T.timeout { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No message from MME")); }
+ }
+ /* We now expect the MME to send a Modify Bearer Request to the SGW-C */
+ f_gtp2_register_udmsg('22'O);
+ T.start;
+ alt {
+ [] as_GTP2C_ModifyBearer_success();
+ [] T.timeout { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No message from MME")); }
+ }
+}
+
+private function f_TC_attach(ConnHdlrPars pars) runs on ConnHdlr {
+ f_init_handler(pars);
+ f_attach();
}
testcase TC_s1ap_attach() runs on MTC_CT {
var charstring id := testcasename();