fixeria submitted this change.

View Change

Approvals: fixeria: Looks good to me, approved Jenkins Builder: Verified
S1GW tests: Add test cases for S1 handover procedure

The test cases expect the handover preparation and resource allocation
to be passed on correctly with expected modifcation of E-RABs.

Related: SYS#7309
Change-Id: Id349c84749f7e897defa8cfd2ecd2c1f2fb52fc7
---
M s1gw/S1GW_ConnHdlr.ttcn
M s1gw/S1GW_Tests.ttcn
M s1gw/expected-results.xml
3 files changed, 323 insertions(+), 1 deletion(-)

diff --git a/s1gw/S1GW_ConnHdlr.ttcn b/s1gw/S1GW_ConnHdlr.ttcn
index 8e01c1f..1d41d0d 100644
--- a/s1gw/S1GW_ConnHdlr.ttcn
+++ b/s1gw/S1GW_ConnHdlr.ttcn
@@ -68,6 +68,22 @@
iE_Extensions := omit
}

+const TargetID c_TargetID := {
+ targeteNB_ID := {
+ global_ENB_ID := {
+ pLMNidentity := '62F210'O,
+ eNB_ID := { homeENB_ID := '0000000000000000000000000000'B },
+ iE_Extensions := omit
+ },
+ selected_TAI := {
+ pLMNidentity := '62F210'O,
+ tAC := '0007'O,
+ iE_Extensions := omit
+ },
+ iE_Extensions := omit
+ }
+}
+
type function void_fn(charstring id) runs on ConnHdlr;

function f_ConnHdlr_init(void_fn fn, charstring id, ConnHdlrPars pars)
@@ -1050,6 +1066,190 @@
PFCP.send(resp);
}

+function f_ConnHdlr_tx_handover_req(in ERabList erabs,
+ MME_UE_S1AP_ID mme_ue_id)
+runs on ConnHdlr {
+ var template (value) E_RABToBeSetupListHOReq items;
+ var template (value) E_RABLevelQoSParameters qos_params;
+
+ qos_params := valueof(ts_E_RABLevelQoSParameters);
+
+ for (var integer i := 0; i < lengthof(erabs); i := i + 1) {
+ var template (value) E_RABToBeSetupItemHOReq item;
+ var template (value) TransportLayerAddress tla;
+ var ERabParams epars := erabs[i].u2c;
+
+ tla := oct2bit(f_inet_addr(epars.tla));
+ item := ts_E_RABToBeSetupItemHOReq(rab_id := erabs[i].erab_id,
+ tla := tla,
+ gtp_teid := epars.teid,
+ qos_params := qos_params);
+ items[i] := ts_E_RABToBeSetupListHOReq(item)[0];
+ }
+
+ f_ConnHdlr_tx_s1ap_from_mme(ts_S1AP_HandoverReq(mme_id := mme_ue_id,
+ ho_type := intralte,
+ cause := { radioNetwork := s1_intra_system_handover_triggered },
+ max_br := ts_UEAggregateMaximumBitrate,
+ rab_setup_items := items,
+ container := '123456'O,
+ ue_sec_par := ts_UESecurityCapabilities,
+ sec_ctx := ts_SecurityContext(5, f_rnd_bitstring(256))));
+}
+
+function f_ConnHdlr_rx_handover_req(in ERabList erabs,
+ MME_UE_S1AP_ID mme_ue_id)
+runs on ConnHdlr return S1AP_PDU {
+ var template (present) E_RABToBeSetupListHOReq items;
+ var S1AP_PDU pdu;
+
+ for (var integer i := 0; i < lengthof(erabs); i := i + 1) {
+ var template (present) E_RABToBeSetupItemHOReq item;
+ var template (present) TransportLayerAddress tla;
+ var ERabParams epars := erabs[i].a2u;
+
+ tla := oct2bit(f_inet_addr(epars.tla));
+ item := tr_E_RABToBeSetupItemHOReq(rab_id := erabs[i].erab_id,
+ tla := tla,
+ gtp_teid := epars.teid,
+ qos_params := ?);
+ items[i] := tr_E_RABToBeSetupListHOReq(item)[0];
+ }
+
+ f_ConnHdlr_rx_s1ap_from_mme(pdu, tr_S1AP_HandoverReq(mme_id := mme_ue_id,
+ ho_type := intralte,
+ cause := { radioNetwork := s1_intra_system_handover_triggered },
+ rab_setup_items := items,
+ container := '123456'O,
+ ue_sec_par := tr_UESecurityCapabilities));
+ return pdu;
+}
+
+function f_ConnHdlr_tx_handover_ack(in ERabList erabs,
+ MME_UE_S1AP_ID mme_ue_id,
+ ENB_UE_S1AP_ID enb_ue_id)
+runs on ConnHdlr {
+ var template (value) E_RABAdmittedList items;
+
+ for (var integer i := 0; i < lengthof(erabs); i := i + 1) {
+ var template (value) E_RABAdmittedItem item;
+ var template (value) TransportLayerAddress tla;
+ var ERabParams epars := erabs[i].u2a;
+
+ tla := oct2bit(f_inet_addr(epars.tla));
+ item := ts_E_RABAdmittedItem(rab_id := erabs[i].erab_id,
+ tla := tla,
+ gtp_teid := epars.teid,
+ dl_tla := omit,
+ dl_gtp_teid := omit,
+ ul_tla := omit,
+ ul_gtp_teid := omit);
+ items[i] := ts_E_RABAdmittedList(item)[0];
+ }
+
+ f_ConnHdlr_tx_s1ap_from_enb(ts_S1AP_HandoverAck(mme_id := mme_ue_id,
+ enb_id := enb_ue_id,
+ rab_admit_items := items,
+ container := '123456'O));
+}
+
+function f_ConnHdlr_rx_handover_ack(in ERabList erabs,
+ MME_UE_S1AP_ID mme_ue_id,
+ ENB_UE_S1AP_ID enb_ue_id)
+runs on ConnHdlr return S1AP_PDU {
+ var template (present) E_RABAdmittedList items;
+ var S1AP_PDU pdu;
+
+ for (var integer i := 0; i < lengthof(erabs); i := i + 1) {
+ var template (present) E_RABAdmittedItem item;
+ var template (present) TransportLayerAddress tla;
+ var ERabParams epars := erabs[i].c2u;
+
+ tla := oct2bit(f_inet_addr(epars.tla));
+ item := tr_E_RABAdmittedItem(rab_id := erabs[i].erab_id,
+ tla := tla,
+ gtp_teid := epars.teid);
+ items[i] := tr_E_RABAdmittedList(item)[0];
+ }
+
+ f_ConnHdlr_rx_s1ap_from_enb(pdu, tr_S1AP_HandoverAck(mme_id := mme_ue_id,
+ enb_id := enb_ue_id,
+ rab_admit_items := items,
+ container := '123456'O));
+ return pdu;
+}
+
+function f_ConnHdlr_tx_handover_rqd(MME_UE_S1AP_ID mme_ue_id,
+ ENB_UE_S1AP_ID enb_ue_id)
+runs on ConnHdlr {
+ f_ConnHdlr_tx_s1ap_from_enb(ts_S1AP_HandoverRqd(mme_id := mme_ue_id,
+ enb_id := enb_ue_id,
+ ho_type := intralte,
+ cause := { radioNetwork := s1_intra_system_handover_triggered },
+ target_id := c_TargetID,
+ container := '123456'O));
+}
+
+function f_ConnHdlr_rx_handover_rqd(MME_UE_S1AP_ID mme_ue_id,
+ ENB_UE_S1AP_ID enb_ue_id)
+runs on ConnHdlr return S1AP_PDU {
+ var S1AP_PDU pdu;
+
+ f_ConnHdlr_rx_s1ap_from_enb(pdu, tr_S1AP_HandoverRqd(mme_id := mme_ue_id,
+ enb_id := enb_ue_id,
+ ho_type := intralte,
+ cause := { radioNetwork := s1_intra_system_handover_triggered },
+ target_id := c_TargetID,
+ container := '123456'O));
+ return pdu;
+}
+
+function f_ConnHdlr_tx_handover_cmd(in ERabList erabs,
+ MME_UE_S1AP_ID mme_ue_id,
+ ENB_UE_S1AP_ID enb_ue_id)
+runs on ConnHdlr {
+ var template (value) E_RABSubjecttoDataForwardingList items;
+
+ for (var integer i := 0; i < lengthof(erabs); i := i + 1) {
+ var template (value) E_RABDataForwardingItem item;
+
+ item := ts_E_RABDataForwardingItem(rab_id := erabs[i].erab_id,
+ dl_tla := omit,
+ dl_gtp_teid := omit,
+ ul_tla := omit,
+ ul_gtp_teid := omit);
+ items[i] := ts_E_RABSubjecttoDataForwardingList(item)[0];
+ }
+
+ f_ConnHdlr_tx_s1ap_from_enb(ts_S1AP_HandoverCmd(mme_id := mme_ue_id,
+ enb_id := enb_ue_id,
+ ho_type := intralte,
+ rab_forward_items := items,
+ container := '123456'O));
+}
+
+function f_ConnHdlr_rx_handover_cmd(in ERabList erabs,
+ MME_UE_S1AP_ID mme_ue_id,
+ ENB_UE_S1AP_ID enb_ue_id)
+runs on ConnHdlr return S1AP_PDU {
+ var template (present) E_RABSubjecttoDataForwardingList items;
+ var S1AP_PDU pdu;
+
+ for (var integer i := 0; i < lengthof(erabs); i := i + 1) {
+ var template (present) E_RABDataForwardingItem item;
+
+ item := tr_E_RABDataForwardingItem(rab_id := erabs[i].erab_id)
+ items[i] := tr_E_RABSubjecttoDataForwardingList(item)[0];
+ }
+
+ f_ConnHdlr_rx_s1ap_from_enb(pdu, tr_S1AP_HandoverCmd(mme_id := mme_ue_id,
+ enb_id := enb_ue_id,
+ ho_type := intralte,
+ rab_forward_items := items,
+ container := '123456'O));
+ return pdu;
+}
+
function f_ConnHdlr_session_establish(inout ERabList erabs)
runs on ConnHdlr {
for (var integer i := 0; i < lengthof(erabs); i := i + 1) {
@@ -1415,4 +1615,84 @@
f_ConnHdlr_rx_s1ap_from_enb(pdu, tr_S1AP_UeContextReleaseCompl(mme_ue_id, enb_ue_id));
}

+function f_ConnHdlr_handover_req_()
+runs on ConnHdlr {
+ f_ConnHdlr_handover_req(g_pars.erabs, g_pars.mme_ue_id);
+}
+
+function f_ConnHdlr_handover_req(inout ERabList erabs,
+ MME_UE_S1AP_ID mme_ue_id)
+runs on ConnHdlr {
+ const OCT8 c_SEID0 := '0000000000000000'O;
+
+ /* This code block cannot be executed by more than one component at a time because
+ * the HANDOVER REQUEST triggers the IUT to send PFCP Session Establishment
+ * Request PDU(s), with need to be routed to the respective ConnHdlr component (us).
+ * As per 3GPP TS 29.244, section 7.2.2.4.2, these PFCP PDUs shall all have SEID=0,
+ * so that the PFCPEM component cannot route them unambiguously. This is why we
+ * need to ensure that only one ConnHdlr is triggering PFCP session establishment
+ * at the given moment of time. */
+ f_Mutex_lock(__BFILE__, __LINE__);
+ f_PFCPEM_subscribe_seid(c_SEID0);
+
+ log("eNB <- [S1GW <- MME]: HANDOVER REQUEST");
+ f_ConnHdlr_tx_handover_req(erabs, mme_ue_id);
+ f_ConnHdlr_session_establish(erabs);
+
+ /* We're done establishing PFCP sessions, so at this point we no longer expect to
+ * receive Session Establishment Request PDUs with SEID=0. Unregister and unlock
+ * the mutex, enabling other components to establish PFCP sessions after us. */
+ f_PFCPEM_unsubscribe_seid(c_SEID0);
+ f_Mutex_unlock(__BFILE__, __LINE__);
+
+ log("[eNB <- S1GW] <- MME: HANDOVER REQUEST");
+ f_ConnHdlr_rx_handover_req(erabs, mme_ue_id);
+}
+
+function f_ConnHdlr_handover_ack_()
+runs on ConnHdlr {
+ f_ConnHdlr_handover_ack(g_pars.erabs, g_pars.mme_ue_id, g_pars.idx);
+}
+
+function f_ConnHdlr_handover_ack(inout ERabList erabs,
+ MME_UE_S1AP_ID mme_ue_id,
+ ENB_UE_S1AP_ID enb_ue_id)
+runs on ConnHdlr {
+ log("[eNB -> S1GW] -> MME: HANDOVER REQUEST ACKNOWLEDGE");
+ f_ConnHdlr_tx_handover_ack(erabs, mme_ue_id, enb_ue_id);
+ f_ConnHdlr_session_modify(erabs);
+ log("eNB -> [S1GW -> MME]: HANDOVER REQUEST ACKNOWLEDGE");
+ f_ConnHdlr_rx_handover_ack(erabs, mme_ue_id, enb_ue_id);
+}
+
+function f_ConnHdlr_handover_rqd_()
+runs on ConnHdlr {
+ f_ConnHdlr_handover_rqd(g_pars.erabs, g_pars.mme_ue_id, g_pars.idx);
+}
+
+function f_ConnHdlr_handover_rqd(in ERabList erabs,
+ MME_UE_S1AP_ID mme_ue_id,
+ ENB_UE_S1AP_ID enb_ue_id)
+runs on ConnHdlr {
+ log("[eNB -> S1GW] -> MME: HANDOVER REQUIRED");
+ f_ConnHdlr_tx_handover_rqd(mme_ue_id, enb_ue_id);
+ log("eNB -> [S1GW -> MME]: HANDOVER REQUIRED");
+ f_ConnHdlr_rx_handover_rqd(mme_ue_id, enb_ue_id);
+}
+
+function f_ConnHdlr_handover_cmd_()
+runs on ConnHdlr {
+ f_ConnHdlr_handover_cmd(g_pars.erabs, g_pars.mme_ue_id, g_pars.idx);
+}
+
+function f_ConnHdlr_handover_cmd(in ERabList erabs,
+ MME_UE_S1AP_ID mme_ue_id,
+ ENB_UE_S1AP_ID enb_ue_id)
+runs on ConnHdlr {
+ log("[eNB -> S1GW] -> MME: HANDOVER COMMAND");
+ f_ConnHdlr_tx_handover_cmd(erabs, mme_ue_id, enb_ue_id);
+ log("eNB -> [S1GW -> MME]: HANDOVER COMMAND");
+ f_ConnHdlr_rx_handover_cmd(erabs, mme_ue_id, enb_ue_id);
+}
+
}
diff --git a/s1gw/S1GW_Tests.ttcn b/s1gw/S1GW_Tests.ttcn
index e6ce2f4..17c63cb 100644
--- a/s1gw/S1GW_Tests.ttcn
+++ b/s1gw/S1GW_Tests.ttcn
@@ -869,6 +869,44 @@
f_UEMuxUEList_all_done(vc_ues);
}

+/* Test Handover Preparation procedures (no change in E-RAB) */
+function f_TC_handover_preparation(charstring id) runs on ConnHdlr {
+ f_ConnHdlr_s1ap_register(g_pars.genb_id);
+ f_ConnHdlr_s1ap_connect(mp_enb_bind_ip, mp_s1gw_enb_ip);
+ f_ConnHdlr_s1ap_setup(g_pars.genb_id);
+
+ f_ConnHdlr_erab_setup_req_();
+ f_ConnHdlr_erab_setup_rsp_();
+ f_ConnHdlr_handover_rqd_();
+ f_ConnHdlr_handover_cmd_();
+ f_ConnHdlr_erab_release_cmd_();
+ f_ConnHdlr_erab_release_rsp_();
+
+ f_ConnHdlr_s1ap_disconnect();
+ f_ConnHdlr_s1ap_unregister(g_pars.genb_id);
+}
+testcase TC_handover_preparation() runs on test_CT {
+ f_TC_exec(refers(f_TC_handover_preparation));
+}
+
+/* Test Handover Resource Allocation procedures */
+function f_TC_handover_res_alloc(charstring id) runs on ConnHdlr {
+ f_ConnHdlr_s1ap_register(g_pars.genb_id);
+ f_ConnHdlr_s1ap_connect(mp_enb_bind_ip, mp_s1gw_enb_ip);
+ f_ConnHdlr_s1ap_setup(g_pars.genb_id);
+
+ f_ConnHdlr_handover_req_();
+ f_ConnHdlr_handover_ack_();
+ f_ConnHdlr_erab_release_cmd_();
+ f_ConnHdlr_erab_release_rsp_();
+
+ f_ConnHdlr_s1ap_disconnect();
+ f_ConnHdlr_s1ap_unregister(g_pars.genb_id);
+}
+testcase TC_handover_res_alloc() runs on test_CT {
+ f_TC_exec(refers(f_TC_handover_res_alloc));
+}
+
function f_TC_pfcp_heartbeat(charstring id) runs on ConnHdlr {
var integer rts := f_PFCPEM_get_recovery_timestamp();
var PDU_PFCP pfcp_pdu;
@@ -917,6 +955,8 @@
execute( TC_uemux_initial_ctx_setup() );
execute( TC_uemux_ue_ctx_release_req() );
execute( TC_uemux_ue_ctx_release_cmd() );
+ execute( TC_handover_preparation() );
+ execute( TC_handover_res_alloc() );
execute( TC_pfcp_heartbeat() );
}

diff --git a/s1gw/expected-results.xml b/s1gw/expected-results.xml
index a44108e..24c0fe0 100644
--- a/s1gw/expected-results.xml
+++ b/s1gw/expected-results.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<testsuite name='S1GW_Tests' tests='31' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+<testsuite name='S1GW_Tests' tests='33' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
<testcase classname='S1GW_Tests' name='TC_setup' time='MASKED'/>
<testcase classname='S1GW_Tests' name='TC_setup_multi' time='MASKED'/>
<testcase classname='S1GW_Tests' name='TC_conn_term_by_mme' time='MASKED'/>
@@ -30,5 +30,7 @@
<testcase classname='S1GW_Tests' name='TC_uemux_initial_ctx_setup' time='MASKED'/>
<testcase classname='S1GW_Tests' name='TC_uemux_ue_ctx_release_req' time='MASKED'/>
<testcase classname='S1GW_Tests' name='TC_uemux_ue_ctx_release_cmd' time='MASKED'/>
+ <testcase classname='S1GW_Tests' name='TC_handover_preparation' time='MASKED'/>
+ <testcase classname='S1GW_Tests' name='TC_handover_res_alloc' time='MASKED'/>
<testcase classname='S1GW_Tests' name='TC_pfcp_heartbeat' time='MASKED'/>
</testsuite>

To view, visit change 41009. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: merged
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: Id349c84749f7e897defa8cfd2ecd2c1f2fb52fc7
Gerrit-Change-Number: 41009
Gerrit-PatchSet: 4
Gerrit-Owner: jolly <andreas@eversberg.eu>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de>
Gerrit-CC: pespin <pespin@sysmocom.de>