mme: Implement missing UE attach steps
Related: OS#6294
Change-Id: Ib4a69aef40bf9dd17d640f650e459668f8415aaa
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();