fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/39145?usp=email )
Change subject: s1gw: add TC_e_rab_modify_ind_cnf[_multi] ......................................................................
s1gw: add TC_e_rab_modify_ind_cnf[_multi]
Test the E-RAB Modify procedure (eNB initiated), which is defined in 3GPP TS 36.413 section 8.2.4.
Change-Id: Iec95ca0ecf37290bddfbefce1861f8ae66bf4db1 --- M s1gw/S1GW_ConnHdlr.ttcn M s1gw/S1GW_Tests.ttcn M s1gw/expected-results.xml 3 files changed, 271 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/45/39145/1
diff --git a/s1gw/S1GW_ConnHdlr.ttcn b/s1gw/S1GW_ConnHdlr.ttcn index 6e5ba99..5c57af4 100644 --- a/s1gw/S1GW_ConnHdlr.ttcn +++ b/s1gw/S1GW_ConnHdlr.ttcn @@ -290,6 +290,7 @@ ERabParams a2u, /* Access -> UPF params */ ERabParams u2a, /* UPF -> Access params */ ERabParams u2cm, /* UPF -> Core params (modified) */ + ERabParams u2am, /* UPF -> Access params (modified) */ OCT8 pfcp_loc_seid, OCT8 pfcp_rem_seid optional }; @@ -518,6 +519,164 @@ return pdu; }
+function f_ConnHdlr_tx_erab_modify_ind(in ERabIdList erabs_modified, + in ERabIdList erabs_not_modified := {}) +runs on ConnHdlr { + var template (value) E_RABToBeModifiedListBearerModInd items_modified; + var template (omit) E_RABNotToBeModifiedListBearerModInd items_not_modified := omit; + var ENB_UE_S1AP_ID enb_ue_id := g_pars.idx; + + for (var integer i := 0; i < lengthof(erabs_modified); i := i + 1) { + var template (value) E_RABToBeModifiedItemBearerModInd item; + var integer erab_idx := erabs_modified[i]; + var ERabParams epars := g_pars.erabs[erab_idx].u2am; + + item := ts_E_RABToBeModifiedItemBearerModInd(rab_id := g_pars.erabs[erab_idx].erab_id, + tla := oct2bit(f_inet_addr(epars.tla)), + gtp_teid := epars.teid); + + items_modified[i] := ts_E_RABToBeModifiedListBearerModInd(item)[0]; + } + + for (var integer i := 0; i < lengthof(erabs_not_modified); i := i + 1) { + var template (value) E_RABNotToBeModifiedItemBearerModInd item; + var integer erab_idx := erabs_not_modified[i]; + var ERabParams epars := g_pars.erabs[erab_idx].u2a; + + item := ts_E_RABNotToBeModifiedItemBearerModInd(rab_id := g_pars.erabs[erab_idx].erab_id, + tla := oct2bit(f_inet_addr(epars.tla)), + gtp_teid := epars.teid); + + items_not_modified[i] := ts_E_RABNotToBeModifiedListBearerModInd(item)[0]; + } + + f_ConnHdlr_tx_s1ap_from_enb(ts_S1AP_RABModifyInd(g_pars.mme_ue_id, enb_ue_id, + rab_do_modify_items := items_modified, + rab_no_modify_items := items_not_modified)); +} + +function f_ConnHdlr_rx_erab_modify_ind(in ERabIdList erabs_modified, + in ERabIdList erabs_not_modified := {}) +runs on ConnHdlr return S1AP_PDU { + var template (present) E_RABToBeModifiedListBearerModInd items_modified; + var template E_RABNotToBeModifiedListBearerModInd items_not_modified := omit; + var ENB_UE_S1AP_ID enb_ue_id := g_pars.idx; + var S1AP_PDU pdu; + + for (var integer i := 0; i < lengthof(erabs_modified); i := i + 1) { + var template (present) E_RABToBeModifiedItemBearerModInd item; + var integer erab_idx := erabs_modified[i]; + var ERabParams epars := g_pars.erabs[erab_idx].c2u; + + item := tr_E_RABToBeModifiedItemBearerModInd(rab_id := g_pars.erabs[erab_idx].erab_id, + tla := oct2bit(f_inet_addr(epars.tla)), + gtp_teid := epars.teid); + + items_modified[i] := tr_E_RABToBeModifiedListBearerModInd(item)[0]; + } + + for (var integer i := 0; i < lengthof(erabs_not_modified); i := i + 1) { + var template (present) E_RABNotToBeModifiedItemBearerModInd item; + var integer erab_idx := erabs_not_modified[i]; + var ERabParams epars := g_pars.erabs[erab_idx].c2u; + + item := tr_E_RABNotToBeModifiedItemBearerModInd(rab_id := g_pars.erabs[erab_idx].erab_id, + tla := oct2bit(f_inet_addr(epars.tla)), + gtp_teid := epars.teid); + + items_not_modified[i] := tr_E_RABNotToBeModifiedListBearerModInd(item)[0]; + } + + f_ConnHdlr_rx_s1ap_from_enb(pdu, tr_S1AP_RABModifyInd(g_pars.mme_ue_id, enb_ue_id, + rab_do_modify_items := items_modified, + rab_no_modify_items := items_not_modified)); + return pdu; +} + +function f_ConnHdlr_tx_erab_modify_cnf(in ERabIdList erabs_modified := {}, + in ERabIdList erabs_not_modified := {}, + in ERabIdList erabs_release := {}) +runs on ConnHdlr { + var template (omit) E_RABModifyListBearerModConf items_modified := omit; + var template (omit) E_RABList items_not_modified := omit; + var template (omit) E_RABList items_release := omit; + var ENB_UE_S1AP_ID enb_ue_id := g_pars.idx; + + for (var integer i := 0; i < lengthof(erabs_modified); i := i + 1) { + var template (value) E_RABModifyItemBearerModConf item; + var integer erab_idx := erabs_modified[i]; + + item := ts_E_RABModifyItemBearerModConf(rab_id := g_pars.erabs[erab_idx].erab_id); + items_modified[i] := ts_E_RABModifyListBearerModConf(item)[0]; + } + + for (var integer i := 0; i < lengthof(erabs_not_modified); i := i + 1) { + var template (value) E_RABItem item; + var integer erab_idx := erabs_not_modified[i]; + + item := ts_E_RABItem(rab_id := g_pars.erabs[erab_idx].erab_id, + cause := { transport := transport_resource_unavailable }); + items_not_modified[i] := ts_E_RABList(item)[0]; + } + + for (var integer i := 0; i < lengthof(erabs_release); i := i + 1) { + var template (value) E_RABItem item; + var integer erab_idx := erabs_release[i]; + + item := ts_E_RABItem(rab_id := g_pars.erabs[erab_idx].erab_id, + cause := { transport := transport_resource_unavailable }); + items_release[i] := ts_E_RABList(item)[0]; + } + + f_ConnHdlr_tx_s1ap_from_mme(ts_S1AP_RABModifyCnf(g_pars.mme_ue_id, enb_ue_id, + rab_modified_items := items_modified, + rab_failed_items := items_not_modified, + rab_release_items := items_release)); +} + +function f_ConnHdlr_rx_erab_modify_cnf(in ERabIdList erabs_modified := {}, + in ERabIdList erabs_not_modified := {}, + in ERabIdList erabs_release := {}) +runs on ConnHdlr return S1AP_PDU { + var template E_RABModifyListBearerModConf items_modified := omit; + var template E_RABList items_not_modified := omit; + var template E_RABList items_release := omit; + var ENB_UE_S1AP_ID enb_ue_id := g_pars.idx; + var S1AP_PDU pdu; + + for (var integer i := 0; i < lengthof(erabs_modified); i := i + 1) { + var template (present) E_RABModifyItemBearerModConf item; + var integer erab_idx := erabs_modified[i]; + + item := tr_E_RABModifyItemBearerModConf(rab_id := g_pars.erabs[erab_idx].erab_id); + items_modified[i] := tr_E_RABModifyListBearerModConf(item)[0]; + } + + for (var integer i := 0; i < lengthof(erabs_not_modified); i := i + 1) { + var template (present) E_RABItem item; + var integer erab_idx := erabs_not_modified[i]; + + item := tr_E_RABItem(rab_id := g_pars.erabs[erab_idx].erab_id, + cause := { transport := transport_resource_unavailable }); + items_not_modified[i] := tr_E_RABList(item)[0]; + } + + for (var integer i := 0; i < lengthof(erabs_release); i := i + 1) { + var template (present) E_RABItem item; + var integer erab_idx := erabs_release[i]; + + item := tr_E_RABItem(rab_id := g_pars.erabs[erab_idx].erab_id, + cause := { transport := transport_resource_unavailable }); + items_release[i] := tr_E_RABList(item)[0]; + } + + f_ConnHdlr_rx_s1ap_from_mme(pdu, tr_S1AP_RABModifyCnf(g_pars.mme_ue_id, enb_ue_id, + rab_modified_items := items_modified, + rab_failed_items := items_not_modified, + rab_release_items := items_release)); + return pdu; +} + private function f_ts_E_RABList(in ERabList erabs, S1AP_IEs.Cause cause) return template (value) E_RABList { @@ -962,6 +1121,64 @@ f_ConnHdlr_rx_erab_modify_rsp(erabs_modified, erabs_failed); }
+function f_ConnHdlr_erab_modify_ind(in ERabIdList erabs_modified, + in ERabIdList erabs_not_modified := {}) +runs on ConnHdlr { + log("[eNB -> S1GW] -> MME: E-RAB MODIFICATION INDICATION"); + f_ConnHdlr_tx_erab_modify_ind(erabs_modified, erabs_not_modified); + /* Expect the S1GW to modify FARs (id=1) of the respective PFCP sessions */ + for (var integer i := 0; i < lengthof(erabs_modified); i := i + 1) { + var E_RAB_ID erab_idx := erabs_modified[i]; + var ERab erab := g_pars.erabs[erab_idx]; + + log("UPF <- S1GW: PFCP Session Modification Request for E-RAB ID ", erab.erab_id); + var PDU_PFCP pdu := f_ConnHdlr_rx_session_modify_req(epars := erab.u2am, + seid := erab.pfcp_loc_seid, + far_id := c_PFCP_FAR_ID_C2A); + log("UPF -> S1GW: PFCP Session Modification Response for E-RAB ID ", erab.erab_id); + f_ConnHdlr_tx_session_modify_resp(erab, pdu); + } + log("eNB -> [S1GW -> MME]: E-RAB MODIFICATION INDICATION"); + f_ConnHdlr_rx_erab_modify_ind(erabs_modified, erabs_not_modified); +} + +function f_ConnHdlr_erab_modify_cnf(in ERabIdList erabs_modified := {}, + in ERabIdList erabs_not_modified := {}, + in ERabIdList erabs_release := {}) +runs on ConnHdlr { + log("eNB <- [S1GW <- MME]: E-RAB MODIFICATION CONFIRMATION"); + f_ConnHdlr_tx_erab_modify_cnf(erabs_modified, erabs_not_modified, erabs_release); + /* For successfully modified E-RABs, U2AM becomes U2A */ + for (var integer i := 0; i < lengthof(erabs_modified); i := i + 1) { + var E_RAB_ID erab_id := erabs_modified[i]; + g_pars.erabs[erab_id].u2a := g_pars.erabs[erab_id].u2am; + } + /* Expect the S1GW to modify (revert) FARs (id=1) for failed E-RABs (if any) */ + for (var integer i := 0; i < lengthof(erabs_not_modified); i := i + 1) { + var E_RAB_ID erab_idx := erabs_not_modified[i]; + var ERab erab := g_pars.erabs[erab_idx]; + + log("UPF <- S1GW: PFCP Session Modification Request for E-RAB ID ", erab.erab_id); + var PDU_PFCP pdu := f_ConnHdlr_rx_session_modify_req(epars := erab.u2a, + seid := erab.pfcp_loc_seid, + far_id := c_PFCP_FAR_ID_C2A); + log("UPF -> S1GW: PFCP Session Modification Response for E-RAB ID ", erab.erab_id); + f_ConnHdlr_tx_session_modify_resp(erab, pdu); + } + /* Expect the S1GW to delete sessions for released E-RABs (if any) */ + if (lengthof(erabs_release) > 0) { + var ERabList erabs; + + for (var integer i := 0; i < lengthof(erabs_release); i := i + 1) { + var E_RAB_ID erab_idx := erabs_release[i]; + erabs[i] := g_pars.erabs[erab_idx]; + } + f_ConnHdlr_session_delete(erabs); + } + log("[eNB <- S1GW] <- MME: E-RAB MODIFICATION CONFIRMATION"); + f_ConnHdlr_rx_erab_modify_cnf(erabs_modified, erabs_not_modified, erabs_release); +} + function f_ConnHdlr_erab_release_cmd(inout ERabList erabs, S1AP_IEs.Cause cause := c_REL_CMD_CAUSE) runs on ConnHdlr { diff --git a/s1gw/S1GW_Tests.ttcn b/s1gw/S1GW_Tests.ttcn index 8b821bc..6d7cba8 100644 --- a/s1gw/S1GW_Tests.ttcn +++ b/s1gw/S1GW_Tests.ttcn @@ -159,6 +159,7 @@ a2u := {'0202'O & uid, "127.0.2.2"}, u2a := {'0002'O & uid, "127.0.0.2"}, u2cm := {'0011'O & uid, "127.127.0.1"}, + u2am := {'0022'O & uid, "127.127.0.2"}, pfcp_loc_seid := seid_prefix & uid, pfcp_rem_seid := omit /* assigned by S1GW */ }; @@ -471,6 +472,54 @@ f_TC_e_rab_modify_req_rsp_exec(num_enbs := mp_multi_enb_num); }
+/* Test E-RAB MODIFICATION Ind/Cnf procedure */ +function f_TC_e_rab_modify_ind_cnf(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(g_pars.erabs); + f_ConnHdlr_erab_setup_rsp(g_pars.erabs); + + /* eNB wants to modify all E-RABs but E-RAB 4 */ + f_ConnHdlr_erab_modify_ind(erabs_modified := {0, 1, 2, 3}, + erabs_not_modified := {4}); + /* MME modifies E-RABs 1 and 3, but not E-RAB 0 and 2 */ + f_ConnHdlr_erab_modify_cnf(erabs_modified := {1, 3}, + erabs_not_modified := {0, 2}); + + /* For the sake of fun, test forwarding of an empty confirmation, + * which is expected to be forwarded unmodified */ + f_ConnHdlr_erab_modify_cnf(); + + f_ConnHdlr_erab_release_cmd(g_pars.erabs); + f_ConnHdlr_erab_release_rsp(g_pars.erabs); + + f_ConnHdlr_s1ap_disconnect(); + f_ConnHdlr_s1ap_unregister(g_pars.genb_id); +} +private function f_TC_e_rab_modify_ind_cnf_exec(integer num_enbs) +runs on test_CT { + var ConnHdlrList vc_conns; + + f_init(); + + for (var integer i := 0; i < num_enbs; i := i + 1) { + var ConnHdlrPars pars := valueof(t_ConnHdlrPars(i, num_erabs := 5)); + vc_conns[i] := f_ConnHdlr_spawn(refers(f_TC_e_rab_modify_ind_cnf), pars); + } + + f_ConnHdlrList_all_done(vc_conns); +} +/* 5 E-RABs at a time, single eNB */ +testcase TC_e_rab_modify_ind_cnf() runs on test_CT { + f_TC_e_rab_modify_ind_cnf_exec(num_enbs := 1); +} +/* 5 E-RABs at a time, multiple eNB connections */ +testcase TC_e_rab_modify_ind_cnf_multi() runs on test_CT { + f_TC_e_rab_modify_ind_cnf_exec(num_enbs := mp_multi_enb_num); +} + /* Test INITIAL CONTEXT SETUP procedure (successful case) */ function f_TC_initial_ctx_setup(charstring id) runs on ConnHdlr { f_ConnHdlr_s1ap_register(g_pars.genb_id); @@ -591,6 +640,8 @@ execute( TC_e_rab_setup_failure() ); execute( TC_e_rab_modify_req_rsp() ); execute( TC_e_rab_modify_req_rsp_multi() ); + execute( TC_e_rab_modify_ind_cnf() ); + execute( TC_e_rab_modify_ind_cnf_multi() ); execute( TC_initial_ctx_setup() ); execute( TC_initial_ctx_setup3() ); execute( TC_initial_ctx_setup_multi() ); diff --git a/s1gw/expected-results.xml b/s1gw/expected-results.xml index 911dda8..8d07117 100644 --- a/s1gw/expected-results.xml +++ b/s1gw/expected-results.xml @@ -1,5 +1,5 @@ <?xml version="1.0"?> -<testsuite name='S1GW_Tests' tests='18' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'> +<testsuite name='S1GW_Tests' tests='20' 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'/> @@ -12,6 +12,8 @@ <testcase classname='S1GW_Tests' name='TC_e_rab_setup_failure' time='MASKED'/> <testcase classname='S1GW_Tests' name='TC_e_rab_modify_req_rsp' time='MASKED'/> <testcase classname='S1GW_Tests' name='TC_e_rab_modify_req_rsp_multi' time='MASKED'/> + <testcase classname='S1GW_Tests' name='TC_e_rab_modify_ind_cnf' time='MASKED'/> + <testcase classname='S1GW_Tests' name='TC_e_rab_modify_ind_cnf_multi' time='MASKED'/> <testcase classname='S1GW_Tests' name='TC_initial_ctx_setup' time='MASKED'/> <testcase classname='S1GW_Tests' name='TC_initial_ctx_setup3' time='MASKED'/> <testcase classname='S1GW_Tests' name='TC_initial_ctx_setup_multi' time='MASKED'/>