pespin has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/42241?usp=email )
Change subject: 5gc: Introduce test TC_handover_inter_ngran_xn
......................................................................
5gc: Introduce test TC_handover_inter_ngran_xn
Change-Id: I4de3f0a02ddbccc85988754a4cd83fe67b1453dc
---
M 5gc/C5G_Tests.ttcn
M 5gc/ConnHdlr.ttcn
M 5gc/expected-results.xml
M library/NGAP_Emulation.ttcn
M library/NGAP_Functions.ttcn
M library/ngap/NGAP_EncDec.cc
M library/ngap/NGAP_Templates.ttcn
M library/ngap/NGAP_Types.ttcn
8 files changed, 228 insertions(+), 16 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks
refs/changes/41/42241/1
diff --git a/5gc/C5G_Tests.ttcn b/5gc/C5G_Tests.ttcn
index 3844f95..028178d 100644
--- a/5gc/C5G_Tests.ttcn
+++ b/5gc/C5G_Tests.ttcn
@@ -613,6 +613,69 @@
vc_conn.done;
}
+/* 3GPP TS 23.502 4.9.1.2.2 Xn based inter NG-RAN handover without User Plane
function re-allocation */
+private function f_TC_handover_inter_ngran_xn_source() runs on ConnHdlr {
+ f_register();
+ f_pdu_sess_establish();
+ f_sleep(1.0);
+ f_ping4(g_pars.ue_pars.sess_pars.run_prog_pars.ping_hostname);
+
+ var NG_NAS_UE_State nus := f_ngap_obtain_nus(g_pars.ue_pars.ran_id);
+
+ /* TODO: conditional, transmit "1a. RAN Usage data report" */
+ COORD.send(Handover_Xn_Pars:{source_amf_id := g_pars.ue_pars.amf_id,
+ guti := g_pars.ue_pars.guti,
+ pti := g_pars.ue_pars.pti,
+ sess_pars := g_pars.ue_pars.sess_pars,
+ kset_id := g_pars.kset_id,
+ nus := nus });
+}
+private function f_TC_handover_inter_ngran_xn_target() runs on ConnHdlr {
+ var Handover_Xn_Pars ho_xn_pars;
+
+ COORD.receive(Handover_Xn_Pars:?) -> value ho_xn_pars;
+ log("HANDOVER STARTED!");
+ g_pars.ue_pars.guti := ho_xn_pars.guti;
+ g_pars.ue_pars.pti := ho_xn_pars.pti;
+ g_pars.ue_pars.sess_pars.id := ho_xn_pars.sess_pars.id;
+ g_pars.ue_pars.sess_pars.cn_gtpu_ip := ho_xn_pars.sess_pars.cn_gtpu_ip;
+ g_pars.ue_pars.sess_pars.cn_gtpu_teid :=
ho_xn_pars.sess_pars.cn_gtpu_teid;
+ g_pars.ue_pars.sess_pars.qos_rules := ho_xn_pars.sess_pars.qos_rules;
+ g_pars.ue_pars.sess_pars.ue_ip := ho_xn_pars.sess_pars.ue_ip;
+ g_pars.kset_id := ho_xn_pars.kset_id;
+
+ f_n2_path_switch(ho_xn_pars.source_amf_id);
+ f_ngap_set_nus(g_pars.ue_pars.ran_id, ho_xn_pars.nus)
+ f_sleep(1.0);
+
+ f_pdu_sess_create_tun();
+ f_ping4(g_pars.ue_pars.sess_pars.run_prog_pars.ping_hostname);
+
+ f_pdu_sess_release();
+ f_deregister();
+}
+testcase TC_handover_inter_ngran_xn() runs on MTC_CT {
+ var ConnHdlr vc_conn[2];
+ var integer i;
+
+ f_init();
+ f_ngap_setup(0);
+ f_ngap_setup(1);
+
+ var ConnHdlrPars pars := f_init_pars(ue_idx := 0, c5g_idx := 0);
+ vc_conn[0] := f_start_handler_create(ngap_idx := 0);
+ vc_conn[1] := f_start_handler_create(ngap_idx := 1);
+ connect(vc_conn[0]:COORD, vc_conn[1]:COORD);
+
+ f_start_handler_run(vc_conn[0],
refers(f_TC_handover_inter_ngran_xn_source), pars);
+ pars.c5g_idx := 1;
+ pars.ue_pars.sess_pars.ran_gtpu_teid :=
int2oct(oct2int(pars.ue_pars.sess_pars.ran_gtpu_teid) + 1, 4);
+ f_start_handler_run(vc_conn[1],
refers(f_TC_handover_inter_ngran_xn_target), pars);
+
+ vc_conn[0].done;
+ vc_conn[1].done;
+}
+
control {
execute( TC_ng_setup() );
execute( TC_ng_setup_unknown_global_gnb_id_plmn() );
@@ -638,6 +701,8 @@
execute( TC_connection_inactive() );
execute( TC_connection_suspend() );
+ execute( TC_handover_inter_ngran_xn() );
+
}
/* TODO:
diff --git a/5gc/ConnHdlr.ttcn b/5gc/ConnHdlr.ttcn
index ce7d38f..da0d3d9 100644
--- a/5gc/ConnHdlr.ttcn
+++ b/5gc/ConnHdlr.ttcn
@@ -49,8 +49,8 @@
import from GTPv1U_Emulation all;
import from UECUPS_Types all;
-/* (maximum) number of emulated eNBs */
-const integer NUM_NGRAN := 1;
+/* (maximum) number of emulated gNBs */
+const integer NUM_NGRAN := 2;
/* parameters of emulated gNB / ng-eNB */
type record NGRANParams {
@@ -112,7 +112,25 @@
boolean exp_CoreNetworkAssistanceInformationForInactive
}
+/* Kind of 3GPP TS 38.423 9.1.1.1 HANDOVER REQUEST plus
+ * 3GPP TS 38.423 8.2.4 RETRIEVE UE CONTEXT RESPONSE (see 9.1.1.9 and 9.2.1.13
too). */
+type record Handover_Xn_Pars {
+ AMF_UE_NGAP_ID source_amf_id,
+ octetstring guti,
+ ProcedureTransactionIdentifier pti,
+ PDUSessionParams sess_pars,
+ NAS_KeySetIdentifier kset_id,
+ NG_NAS_UE_State nus /* 3GPP TS 38.423 9.2.1.13 UE Context Information */
+};
+
+type port ConnHdlr_Coord_PT message
+{
+ inout charstring, Handover_Xn_Pars;
+} with { extension "internal" };
+
type component ConnHdlr extends NGAP_ConnHdlr, GTP1U_ConnHdlr {
+ port ConnHdlr_Coord_PT COORD;
+
var ConnHdlrPars g_pars;
var UeDerivedKeys g_keys;
@@ -217,6 +235,16 @@
return valueof(st);
}
+function f_UESecurityCapabilities() runs on ConnHdlr return
UESecurityCapabilities
+{
+ var template (value) UESecurityCapabilities cap;
+ cap := m_uESecurityCapabilities(p_nRencryptionAlgorithms :=
'0000000000000000'B,
+ p_nRintegrityProtectionAlgorithms :=
'0000000000000000'B,
+ p_eUTRAencryptionAlgorithms :=
'0000000000000000'B,
+ p_eUTRAintegrityProtectionAlgorithms :=
'0000000000000000'B);
+ return valueof(cap);
+}
+
/* 3GPP TS 24.501 5.4.1.3.2, 3GPP TS 33.501 6.1.3.2 */
private altstep as_ngap_handle_auth(boolean allow_resync := true) runs on
ConnHdlr {
var NG_NAS_DL_Message_Type rx_nas;
@@ -881,6 +909,43 @@
g_pars.ue_pars.ran_id)));
}
+/* 3GPP TS 38.413 8.4.4 Path Switch Request
+ * 3GPP TS 38.413 9.2.3.8 PATH SWITCH REQUEST
+ * 3GPP TS 23.502 4.9.1.2.2 Xn based inter NG-RAN handover without User Plane
function re-allocation */
+function f_n2_path_switch(AMF_UE_NGAP_ID source_amf_id) runs on ConnHdlr
+{
+ var template (value) UPTransportLayerInformation utla;
+ var template (value) PathSwitchRequestTransfer transfer;
+ var octetstring transfer_enc;
+ var template (value) PDUSessionResourceToBeSwitchedDLItem it;
+ var template (value) NGAP_PDU tx_pdu;
+ var NGAP_PDU rx_pdu;
+
+ utla := m_uPTransportLayerInformation_gTPTunnel(
+ m_gTPTunnel(p_tla :=
oct2bit(f_inet_addr(g_pars.ue_pars.sess_pars.ran_gtpu_ip)),
+ p_gtp_teid :=
g_pars.ue_pars.sess_pars.ran_gtpu_teid));
+ transfer := m_pathSwitchRequestTransfer(p_dL_NGU_UP_TNLInformation :=
utla,
+ p_qosFlowAcceptedList := {
m_qosFlowAcceptedItem(1) },
+ p_dL_NGU_TNLInformationReused
:= omit,
+ p_userPlaneSecurityInformation
:= omit);
+ transfer_enc := enc_NGAP_PathSwitchRequestTransfer(valueof(transfer));
+ it :=
m_pDUSessionResourceToBeSwitchedDLItem(g_pars.ue_pars.sess_pars.id,
+ transfer_enc);
+
+ tx_pdu := m_ngap_initMsg(m_n2_PathSwitchRequest(
+ g_pars.ue_pars.ran_id,
+ source_amf_id,
+ f_ULI(),
+ f_UESecurityCapabilities(),
+ { it }));
+ NGAP.send(tx_pdu);
+ NGAP.receive(mw_ngap_succMsg(mw_n2_PathSwitchRequestAcknowledge(?,
g_pars.ue_pars.ran_id))) -> value rx_pdu;
+
+ /* Update amf_id: */
+ var PathSwitchRequestAcknowledge path_switch_ack :=
rx_pdu.successfulOutcome.value_.PathSwitchRequestAcknowledge;
+ g_pars.ue_pars.amf_id :=
path_switch_ack.protocolIEs[0].value_.aMF_UE_NGAP_ID;
+}
+
/* Handle a PDUSessionResourceSetupRequestTransfer contained inside NGAP
InitialContextSetupRequest and return a Result for InitialContextSetupResponse
*/
private function
f_pdu_handle_session_resource_released_item(PDUSessionResourceToReleaseItemRelCmd
cmd) runs on ConnHdlr return PDUSessionResourceReleasedItemRelRes
{
diff --git a/5gc/expected-results.xml b/5gc/expected-results.xml
index 22a18be..2333f8d 100644
--- a/5gc/expected-results.xml
+++ b/5gc/expected-results.xml
@@ -23,4 +23,5 @@
C5G_Tests.ttcn:MASKED TC_connection_suspend testcase
</failure>
</testcase>
+ <testcase classname='C5G_Tests' name='TC_handover_inter_ngran_xn'
time='MASKED'/>
</testsuite>
diff --git a/library/NGAP_Emulation.ttcn b/library/NGAP_Emulation.ttcn
index 22eb605..d050d2f 100644
--- a/library/NGAP_Emulation.ttcn
+++ b/library/NGAP_Emulation.ttcn
@@ -117,12 +117,16 @@
signature NGAPEM_register(in AMF_UE_NGAP_ID amf_id, in RAN_UE_NGAP_ID ran_id,
in NGAP_ConnHdlr hdlr);
signature NGAPEM_register_proc(in integer procedureCode, in NGAP_ConnHdlr
hdlr);
signature NGAPEM_obtain_amf_id() return AMF_UE_NGAP_ID;
+signature NGAPEM_obtain_nus(in RAN_UE_NGAP_ID ran_id) return NG_NAS_UE_State;
+signature NGAPEM_set_nus(in RAN_UE_NGAP_ID ran_id, in NG_NAS_UE_State nus);
//signature NGAPEM_derive_nas_token(in octetstring kasme, in NGAP_ConnHdlr
hdlr, out OCT32 nas_token);
type port NGAPEM_PROC_PT procedure {
inout NGAPEM_register;
inout NGAPEM_register_proc;
inout NGAPEM_obtain_amf_id;
+ inout NGAPEM_obtain_nus;
+ inout NGAPEM_set_nus;
//inout NGAPEM_derive_nas_token;
} with { extension "internal" };
@@ -288,13 +292,18 @@
return -1; /* make ttcn3 compiler happy */
}
-private function f_assoc_id_by_comp(NGAP_ConnHdlr client)
+private function f_assoc_id_by_comp(NGAP_ConnHdlr client, template (omit)
RAN_UE_NGAP_ID ran_id := omit)
runs on NGAP_Emulation_CT return integer {
var integer i;
for (i := 0; i < sizeof(NGapAssociationTable); i := i+1) {
- if (NGapAssociationTable[i].comp_ref == client) {
- return i;
+ if (NGapAssociationTable[i].comp_ref != client) {
+ continue;
}
+ if (not istemplatekind(ran_id, "omit") and
+ not match(NGapAssociationTable[i].ran_ue_ngap_id, ran_id)) {
+ continue;
+ }
+ return i;
}
setverdict(fail, "NGAP Association Table not found by component ",
client);
mtc.stop;
@@ -481,6 +490,7 @@
var charstring vlr_name, amf_name;
var integer ai;
var octetstring kasme;
+ var NG_NAS_UE_State nus;
alt {
/* Configuration primitive from client */
@@ -518,6 +528,15 @@
/* Pass message through */
NGAP.send(t_NGAP_Send(g_ngap_conn_id, msg));
}
+ /* NGAP from client: PathSwitch */
+ []
NGAP_CLIENT.receive(mw_ngap_initMsg(mw_n2_PathSwitchRequest)) -> value msg
sender vc_conn {
+ /* create a table entry about this connection */
+ ai := f_ngap_id_table_add(vc_conn, omit,
valueof(f_NGAP_get_RAN_UE_NGAP_ID(msg)));
+ /* Store ULI so we can use it for generating
UlNasTransport from NAS */
+ NGapAssociationTable[ai].uli :=
msg.initiatingMessage.value_.PathSwitchRequest.protocolIEs[2].value_.userLocationInformation;
+ /* Pass message through */
+ NGAP.send(t_NGAP_Send(g_ngap_conn_id, msg));
+ }
/* NAS from client: Wrap in NGAP Uplink NAS Transport */
[] NGAP_CLIENT.receive(NG_NAS_UL_Message_Type:?) -> value
ul_nas_msg sender vc_conn {
var integer assoc_id := f_assoc_id_by_comp(vc_conn);
@@ -612,6 +631,15 @@
amf_id := NGapAssociationTable[i].amf_ue_ngap_id;
NGAP_PROC.reply(NGAPEM_obtain_amf_id:{} value amf_id)
to vc_conn;
}
+ [] NGAP_PROC.getcall(NGAPEM_obtain_nus:{?}) -> param(ran_id)
sender vc_conn {
+ var integer i := f_assoc_id_by_comp(vc_conn, ran_id);
+ NGAP_PROC.reply(NGAPEM_obtain_nus:{ran_id} value
NGapAssociationTable[i].nus) to vc_conn;
+ }
+ [] NGAP_PROC.getcall(NGAPEM_set_nus:{?, ?}) -> param(ran_id,
nus) sender vc_conn {
+ var integer i := f_assoc_id_by_comp(vc_conn, ran_id);
+ NGapAssociationTable[i].nus := nus;
+ NGAP_PROC.reply(NGAPEM_set_nus:{ran_id, nus}) to
vc_conn;
+ }
// [] NGAP_PROC.getcall(NGAPEM_derive_nas_token:{?, ?, -}) ->
param(kasme, vc_conn) {
// var integer assoc_id := f_assoc_id_by_comp(vc_conn);
// var OCT32 nas_token := f_kdf_nas_token(kasme,
NGapAssociationTable[assoc_id].nus.tx_count)
@@ -721,4 +749,19 @@
}
}
+function f_ngap_obtain_nus(RAN_UE_NGAP_ID ran_id) runs on NGAP_ConnHdlr return
NG_NAS_UE_State {
+ var NG_NAS_UE_State nus;
+ NGAP_PROC.call(NGAPEM_obtain_nus:{ran_id}) {
+ [] NGAP_PROC.getreply(NGAPEM_obtain_nus:{ran_id}) -> value nus {
+ return nus;
+ }
+ }
+}
+
+function f_ngap_set_nus(RAN_UE_NGAP_ID ran_id, NG_NAS_UE_State nus) runs on
NGAP_ConnHdlr {
+ NGAP_PROC.call(NGAPEM_set_nus:{ran_id, nus}) {
+ [] NGAP_PROC.getreply(NGAPEM_set_nus:{ran_id, nus});
+ }
+}
+
}
diff --git a/library/NGAP_Functions.ttcn b/library/NGAP_Functions.ttcn
index e1fcf6d..5d45c43 100644
--- a/library/NGAP_Functions.ttcn
+++ b/library/NGAP_Functions.ttcn
@@ -45,6 +45,9 @@
} else if (ischosen(ngap.successfulOutcome)) {
var SuccessfulOutcome so := ngap.successfulOutcome;
select (so.procedureCode) {
+ case (id_PathSwitchRequest) {
+ return
so.value_.PathSwitchRequestAcknowledge.protocolIEs[0].value_.aMF_UE_NGAP_ID;
+ }
case (?) {
return omit;
/* TODO */
@@ -92,11 +95,17 @@
case (id_PDUSessionResourceRelease) {
return
im.value_.pDUSessionResourceReleaseCommand.protocolIEs[1].value_.rAN_UE_NGAP_ID;
}
+ case (id_PathSwitchRequest) {
+ return
im.value_.PathSwitchRequest.protocolIEs[0].value_.RAN_UE_NGAP_ID;
+ }
/* TODO */
}
} else if (ischosen(ngap.successfulOutcome)) {
var SuccessfulOutcome so := ngap.successfulOutcome;
select (so.procedureCode) {
+ case (id_PathSwitchRequest) {
+ return
so.value_.PathSwitchRequestAcknowledge.protocolIEs[1].value_.rAN_UE_NGAP_ID;
+ }
case (?) {
return omit;
/* TODO */
diff --git a/library/ngap/NGAP_EncDec.cc b/library/ngap/NGAP_EncDec.cc
index 8b825d5..9e3ccd2 100644
--- a/library/ngap/NGAP_EncDec.cc
+++ b/library/ngap/NGAP_EncDec.cc
@@ -129,4 +129,24 @@
return ret;
}
+OCTETSTRING enc__NGAP__PathSwitchRequestTransfer(const
NGAP__IEs::PathSwitchRequestTransfer &p)
+{
+ TTCN_Buffer TTCN_buf;
+ TTCN_buf.clear();
+ p.encode(NGAP__IEs::PathSwitchRequestTransfer_descr_, TTCN_buf,
+ TTCN_EncDec::CT_PER, PER_ALIGNED);
+ return OCTETSTRING(TTCN_buf.get_len(), TTCN_buf.get_data());
+}
+
+NGAP__IEs::PathSwitchRequestTransfer
dec__NGAP__PathSwitchRequestTransfer(const OCTETSTRING &stream)
+{
+ NGAP__IEs::PathSwitchRequestTransfer ret;
+ TTCN_Buffer TTCN_buf;
+ TTCN_buf.clear();
+ TTCN_buf.put_os(stream);
+ ret.decode(NGAP__IEs::PathSwitchRequestTransfer_descr_, TTCN_buf,
+ TTCN_EncDec::CT_PER, PER_ALIGNED);
+ return ret;
+}
+
}
diff --git a/library/ngap/NGAP_Templates.ttcn b/library/ngap/NGAP_Templates.ttcn
index 0931687..6626cc1 100644
--- a/library/ngap/NGAP_Templates.ttcn
+++ b/library/ngap/NGAP_Templates.ttcn
@@ -4891,16 +4891,16 @@
PathSwitchRequest := {
protocolIEs := {
{
-
id := id_AMF_UE_NGAP_ID,
-
criticality := reject,
-
value_ := { AMF_UE_NGAP_ID := p_amfUeNgapID }
-
},
-
{
id := id_RAN_UE_NGAP_ID,
criticality := reject,
value_ := { RAN_UE_NGAP_ID := p_ranUeNgapID }
},
{
+
id := id_SourceAMF_UE_NGAP_ID,
+
criticality := reject,
+
value_ := { AMF_UE_NGAP_ID := p_amfUeNgapID }
+
},
+
{
id := id_UserLocationInformation,
criticality := ignore,
value_ := { UserLocationInformation := p_userLocationInformation }
@@ -4940,16 +4940,16 @@
PathSwitchRequest := {
protocolIEs := {
{
-
id := id_AMF_UE_NGAP_ID,
-
criticality := reject,
-
value_ := { AMF_UE_NGAP_ID := p_amfUeNgapID }
-
},
-
{
id := id_RAN_UE_NGAP_ID,
criticality := reject,
value_ := { RAN_UE_NGAP_ID := p_ranUeNgapID }
},
{
+
id := id_SourceAMF_UE_NGAP_ID,
+
criticality := reject,
+
value_ := { AMF_UE_NGAP_ID := p_amfUeNgapID }
+
},
+
{
id := id_UserLocationInformation,
criticality := ignore,
value_ := { UserLocationInformation := p_userLocationInformation }
@@ -5027,7 +5027,8 @@
template (present) AMF_UE_NGAP_ID p_amfUeNgapID := ?,
template (present) RAN_UE_NGAP_ID p_ranUeNgapID := ?,
template (present) SecurityContext p_securityContext := ?,
-
template (present) PDUSessionResourceSwitchedList
p_pDUSessionResourceSwitchedList := ?
+
template (present) PDUSessionResourceSwitchedList
p_pDUSessionResourceSwitchedList := ?,
+
template (present) AllowedNSSAI p_allowedNSSAI := ?
) := {
procedureCode := id_PathSwitchRequest,
criticality := reject,
@@ -5053,6 +5054,11 @@
id := id_PDUSessionResourceSwitchedList,
criticality := ignore,
value_ := { PDUSessionResourceSwitchedList :=
p_pDUSessionResourceSwitchedList }
+
},
+
{
+
id := id_AllowedNSSAI,
+
criticality := reject,
+
value_ := { AllowedNSSAI := p_allowedNSSAI }
}
}
}
diff --git a/library/ngap/NGAP_Types.ttcn b/library/ngap/NGAP_Types.ttcn
index d9523b4..394cb24 100644
--- a/library/ngap/NGAP_Types.ttcn
+++ b/library/ngap/NGAP_Types.ttcn
@@ -20,4 +20,7 @@
external function
enc_NGAP_UEContextSuspendRequestTransfer(NGAP_IEs.UEContextSuspendRequestTransfer
p) return octetstring;
external function dec_NGAP_UEContextSuspendRequestTransfer(in
octetstring pdu) return NGAP_IEs.UEContextSuspendRequestTransfer;
+
+ external function
enc_NGAP_PathSwitchRequestTransfer(NGAP_IEs.PathSwitchRequestTransfer p) return
octetstring;
+ external function dec_NGAP_PathSwitchRequestTransfer(in octetstring
pdu) return NGAP_IEs.PathSwitchRequestTransfer;
}
--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/42241?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I4de3f0a02ddbccc85988754a4cd83fe67b1453dc
Gerrit-Change-Number: 42241
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <[email protected]>