pespin has submitted this change. (
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/40408?usp=email )
Change subject: 5gc: Initial NAS receiving support
......................................................................
5gc: Initial NAS receiving support
With this patch it is already possible to receive the NAS Auth Request
in the test ConnHdlr.
nas.git dep needs updating to include a new patch fixing decoding of
NG_AUTHENTICATION_REQUEST.
Change-Id: I6697f30f95777fc9aed16a529a669d10f42c57be
---
M 5gc/C5G_Tests.ttcn
M 5gc/create_test_subscribers.sh
M 5gc/gen_links.sh
M deps/Makefile
M library/NGAP_Emulation.ttcn
M library/NGAP_Functions.ttcn
A library/NG_NAS_Osmo_Templates.ttcn
M library/Osmocom_Types.ttcn
8 files changed, 273 insertions(+), 96 deletions(-)
Approvals:
pespin: Looks good to me, approved
osmith: Looks good to me, but someone else must approve
Jenkins Builder: Verified
diff --git a/5gc/C5G_Tests.ttcn b/5gc/C5G_Tests.ttcn
index 62553fc..320d61f 100644
--- a/5gc/C5G_Tests.ttcn
+++ b/5gc/C5G_Tests.ttcn
@@ -17,6 +17,7 @@
import from Misc_Helpers all;
import from Osmocom_Types all;
+import from GSM_Types all;
import from NGAP_PDU_Descriptions all;
import from NGAP_IEs all;
@@ -29,10 +30,14 @@
import from NGAP_Functions all;
import from NGAP_Emulation all;
+import from NAS_CommonTypeDefs all;
+
import from NG_NAS_Common all;
import from NG_NAS_MsgContainers all;
import from NAS_CommonTemplates all;
import from NG_NAS_Templates all;
+
+import from NG_NAS_Osmo_Templates all;
import from NG_NAS_Functions all;
/* (maximum) number of emulated eNBs */
@@ -48,7 +53,9 @@
integer mp_5gc_ngap_port := 38412;
charstring mp_local_ngap_ip := "127.0.0.1";
integer mp_local_ngap_port := 50000;
- PLMNIdentity mp_plmn_id := '99f907'O;
+ GsmMcc mp_mcc := '999'H;
+ GsmMnc mp_mnc := '70'H;
+ hexstring mp_imsi := '999700000000000'H;
uint24_t mp_tac := 1;
}
@@ -86,9 +93,9 @@
/* copied over from MTC_CT on start of component */
UeParams ue_pars,
/* currently used 5GC (index into ngran_pars, NGAP, ...) */
- integer c5g_idx//,
+ integer c5g_idx,
/* Currently set KSI */
- //NAS_KeySetIdentifierV kset_id
+ NAS_KeySetIdentifier kset_id
}
/* send incoming unit data messages (like reset) to global NGAP_UNIT port */
@@ -108,17 +115,18 @@
remote_ip := mp_5gc_ngap_ip,
remote_sctp_port := mp_5gc_ngap_port,
local_ip := mp_local_ngap_ip,
- local_sctp_port := mp_local_ngap_port + num //,
- //role := NAS_ROLE_UE
+ local_sctp_port := mp_local_ngap_port + num,
+ role := NGAP_NAS_ROLE_UE
};
+ var PLMNIdentity plmn_id := f_enc_mcc_mnc(mp_mcc, mp_mnc);
var NGRANParams ngran_pars := {
- global_ngran_id := valueof(m_globalRANNodeID_globalGNB_ID(m_ie_globalGnbId(mp_plmn_id,
int2bit(num, 22)))),
- cell_identity := { nR_CGI := valueof(m_nR_CGI(mp_plmn_id, int2bit(num, 36))) },
+ global_ngran_id := valueof(m_globalRANNodeID_globalGNB_ID(m_ie_globalGnbId(plmn_id,
int2bit(num, 22)))),
+ cell_identity := { nR_CGI := valueof(m_nR_CGI(plmn_id, int2bit(num, 36))) },
supported_ta_list := {
{
tAC := int2oct(mp_tac, 3),
broadcastPLMNList := {
- valueof(m_ie_broadcastPLMNItem(mp_plmn_id, {
m_sliceSupportItem(m_s_NSSAI('01'O)) }))
+ valueof(m_ie_broadcastPLMNItem(plmn_id, {
m_sliceSupportItem(m_s_NSSAI('01'O)) }))
},
iE_Extensions := omit
}
@@ -136,17 +144,17 @@
friend function f_init_one_ue(inout UeParams uep, integer imsi_suffix) {
uep := {
- imsi := f_gen_imsi(imsi_suffix),
+ imsi := f_concat_pad(lengthof(mp_imsi), substr(mp_imsi, 0, lengthof(mp_imsi) - 6),
imsi_suffix),
ue_ip := "192.168.123.50"
}
}
-friend function f_init_ngap(integer imsi_suffix) runs on MTC_CT {
+friend function f_init_ngap(integer imsi_suffix := 0) runs on MTC_CT {
var integer i;
for (i := 0; i < NUM_NGRAN; i := i+1) {
f_init_one_ngran(i);
}
for (i := 0; i < NUM_UE; i := i+1) {
- f_init_one_ue(g_ue_pars[i], i*1000 + imsi_suffix);
+ f_init_one_ue(g_ue_pars[i], 1000*imsi_suffix + i);
}
}
@@ -156,8 +164,8 @@
var ConnHdlrPars pars := {
ngran_pars := g_ngran_pars,
ue_pars := g_ue_pars[ue_idx],
- c5g_idx := 0//,
- //kset_id := valueof(ts_NAS_KeySetIdentifierV('000'B,
c_NAS_TSC_NATIVE_SEC_CTX))
+ c5g_idx := 0,
+ kset_id := valueof(cs_NAS_KeySetIdentifier_lv(tsc_NasKsi_NoKey, '0'B))
};
return pars;
}
@@ -203,6 +211,14 @@
iE_Extensions := omit
}
+private function f_SUCI_IMSI() runs on ConnHdlr return octetstring {
+ var hexstring imsi := g_pars.ue_pars.imsi;
+ var GsmMcc mcc := substr(imsi, 0, 3);
+ var GsmMnc mnc := substr(imsi, 3, 2);
+ var octetstring imsi_suffix := imsi_hex2oct(substr(imsi, lengthof(imsi)-10, 10));
+ return f_enc_mcc_mnc(mcc, mnc) & '21430001'O & imsi_suffix;
+}
+
friend function f_ngap_setup(integer idx := 0, template (omit) NGAP_IEs.Cause cause :=
omit) runs on MTC_CT {
var template (present) NGAP_IEs.Cause exp_cause := ?;
var boolean exp_fail := false;
@@ -243,6 +259,25 @@
}
}
+private function f_tr_ConnHdlr_kset_id() runs on ConnHdlr return template (present)
NAS_KeySetIdentifier {
+ /* KSI not yet set, expect whatever assignment from network: */
+ if (g_pars.kset_id.nasKeySetId == tsc_NasKsi_NoKey) {
+ return cr_NAS_KeySetIdentifier(?, ?);
+ } else {
+ /* Expect specific kset_id. Upon transmitting it UE->Network, f_attach()
+ * has updated it to the expected value. */
+ return g_pars.kset_id;
+ }
+}
+
+private altstep as_ngap_handle_auth() runs on ConnHdlr {
+ var NG_NAS_DL_Message_Type rx_nas;
+ var template (present) NAS_KeySetIdentifier kset_id := f_tr_ConnHdlr_kset_id();
+ [] NGAP.receive(cr_NG_AUTHENTICATION_REQUEST) -> value rx_nas {
+ log("Rx NAS message: ", rx_nas);
+ }
+}
+
private function f_register() runs on ConnHdlr {
var template (value) UserLocationInformation p_ueLocInf;
var template (value) NGAP_PDU tx_pdu;
@@ -258,10 +293,11 @@
));
nas_ul_msg := cs_NG_REGISTRATION_REQUEST(cs_RegistrationType(tsc_NG_RegistrationInitial,
'1'B),
- tsc_NasKsi_NoKey,
- '0'B,
+ g_pars.kset_id.nasKeySetId,
+ g_pars.kset_id.tsc,
cs_NG_MobileIdentitySUCI('0000'B /* Type IMSI */,
- '00f110214300014444330302'O));
+ f_SUCI_IMSI()),
+ p_UESecurityCap := cs_NG_UE_SecurityCapability);
nas_pdu := enc_NG_NAS_UL_Message_Type(valueof(nas_ul_msg));
@@ -271,7 +307,7 @@
mo_Signalling));
NGAP.send(tx_pdu);
- f_sleep(5.0);
+ as_ngap_handle_auth();
/* TODO: handle Auth, SecurityModeCommand, InitialContextSetup, PDUSessionresource, */
}
@@ -279,21 +315,21 @@
/* NG Setup procedure to 5GC using a Global gNB ID containing unknown/foreign PLMN.
* Related:
https://github.com/open5gs/open5gs/issues/3544 */
testcase TC_ng_setup_unknown_global_gnb_id_plmn() runs on MTC_CT {
- f_init_ngap(1);
+ f_init_ngap();
g_ngran_pars[0].global_ngran_id.globalGNB_ID.pLMNIdentity := '62F224'O;
f_ngap_setup(0);
}
/* Unsuccessful NG Setup procedure to AMF (wrong PLMN) */
testcase TC_ng_setup_wrong_tac() runs on MTC_CT {
- f_init_ngap(2);
+ f_init_ngap();
g_ngran_pars[0].supported_ta_list[0].broadcastPLMNList[0].pLMNIdentity :=
'62F224'O;
f_ngap_setup(0, {misc:=unknown_PLMN_or_SNPN});
}
/* NG Setup procedure to 5GC using a correct Global gNB ID. */
testcase TC_ng_setup() runs on MTC_CT {
- f_init_ngap(3);
+ f_init_ngap();
f_ngap_setup(0);
}
@@ -302,7 +338,7 @@
f_register();
}
testcase TC_ng_register() runs on MTC_CT {
- f_init_ngap(4);
+ f_init_ngap();
f_ngap_setup(0);
var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
diff --git a/5gc/create_test_subscribers.sh b/5gc/create_test_subscribers.sh
index f5b6c5b..a400e0f 100755
--- a/5gc/create_test_subscribers.sh
+++ b/5gc/create_test_subscribers.sh
@@ -18,10 +18,10 @@
done
# Create a test subscriber with IMSI=001010000000000
-$DBCTL_CMD add 001010000000000 3c6e0b8a9c15224a8228b9a98ca1531d
762a2206fe0b4151ace403c86a11e479
+$DBCTL_CMD add 999700000000000 3c6e0b8a9c15224a8228b9a98ca1531d
762a2206fe0b4151ace403c86a11e479
# Mark test subscriber with IMSI=001010000000001 as:
# Subscriber-Status=OPERATOR_DETERMINED_BARRING (1)
# Operator-Determined-Barring="Barring of all outgoing inter-zonal calls except
those directed to the home PLMN country" (7)
-$DBCTL_CMD add 001010000000001 3c6e0b8a9c15224a8228b9a98ca1531d
762a2206fe0b4151ace403c86a11e479
-$DBCTL_CMD subscriber_status 001010000000001 1 7
+$DBCTL_CMD add 999700000000001 3c6e0b8a9c15224a8228b9a98ca1531d
762a2206fe0b4151ace403c86a11e479
+$DBCTL_CMD subscriber_status 999700000000001 1 7
diff --git a/5gc/gen_links.sh b/5gc/gen_links.sh
index 2cab445..295ca24 100755
--- a/5gc/gen_links.sh
+++ b/5gc/gen_links.sh
@@ -66,7 +66,7 @@
FILES+="SCTP_Templates.ttcn "
FILES+="DNS_Helpers.ttcn "
FILES+="NGAP_CodecPort.ttcn NGAP_CodecPort_CtrlFunctDef.cc
NGAP_CodecPort_CtrlFunct.ttcn NGAP_Functions.ttcn NGAP_Emulation.ttcn "
-FILES+="NG_NAS_Functions.ttcn "
+FILES+="NG_NAS_Osmo_Templates.ttcn NG_NAS_Functions.ttcn "
gen_links $DIR $FILES
gen_links_finish
diff --git a/deps/Makefile b/deps/Makefile
index b4a411a..aa2b36c 100644
--- a/deps/Makefile
+++ b/deps/Makefile
@@ -85,7 +85,7 @@
# Do not put references to branches here, except for local testing: this breaks the
caching
# logic of docker containers, which only invalidate their cached ttcn3 dependencies if
this
# file changed.
-nas_commit= 205e24167517500ba2d49322dfa1754ab8a0fc43
+nas_commit= 4371752494b7c85cd5a3bc32bc6f498171c7aa13
titan.Libraries.TCCUsefulFunctions_commit= R.35.B-6-gb3687da
titan.ProtocolEmulations.M3UA_commit= b58f92046e48a7b1ed531e243a2319ebca53bf4c
titan.ProtocolEmulations.SCCP_commit= 750a3e836831e58eae59d4757ef5d0c759f9ca5d
diff --git a/library/NGAP_Emulation.ttcn b/library/NGAP_Emulation.ttcn
index e885a4d..46f1d63 100644
--- a/library/NGAP_Emulation.ttcn
+++ b/library/NGAP_Emulation.ttcn
@@ -33,8 +33,16 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
+import from General_Types all;
+import from Osmocom_Types all;
+import from IPL4asp_Types all;
+import from DNS_Helpers all;
+
+import from SCTP_Templates all;
+
import from NGAP_CodecPort all;
import from NGAP_CodecPort_CtrlFunct all;
+import from NGAP_CommonDataTypes all;
import from NGAP_Types all;
import from NGAP_Constants all;
import from NGAP_PDU_Contents all;
@@ -42,13 +50,14 @@
import from NGAP_IEs all;
import from NGAP_Templates all;
import from NGAP_Functions all;
-import from SCTP_Templates all;
-import from General_Types all;
-import from Osmocom_Types all;
-import from IPL4asp_Types all;
-import from DNS_Helpers all;
+import from NG_NAS_MsgContainers all;
+import from NG_NAS_Functions all;
+type enumerated NGAP_NAS_Role {
+ NGAP_NAS_ROLE_UE, /* ATS implements/emulates UE */
+ NGAP_NAS_ROLE_AMF /* ATS implements/emulates AMF */
+};
type component NGAP_ConnHdlr {
port NGAP_Conn_PT NGAP;
@@ -58,7 +67,7 @@
/* port between individual per-connection components and this dispatcher */
type port NGAP_Conn_PT message {
- inout NGAP_PDU;
+ inout NGAP_PDU, NG_NAS_UL_Message_Type, NG_NAS_DL_Message_Type;
} with { extension "internal" };
@@ -135,7 +144,7 @@
type record AssociationData {
NGAP_ConnHdlr comp_ref, /* component handling this UE connection */
uint32_t ran_ue_ngap_id optional, /* eNB side NGAP ID */
- uint40_t amf_ue_ngap_id optional//, /* MME side NGAP ID */
+ uint40_t amf_ue_ngap_id optional//, /* AMF side NGAP ID */
//EUTRAN_CGI cgi optional,
//TAI tai optional,
//NAS_UE_State nus
@@ -182,8 +191,8 @@
HostName remote_ip,
IPL4asp_Types.PortNumber remote_sctp_port,
HostName local_ip,
- IPL4asp_Types.PortNumber local_sctp_port//,
- //NAS_Role role
+ IPL4asp_Types.PortNumber local_sctp_port,
+ NGAP_NAS_Role role
}
function tr_NGAP_RecvFrom_R(template NGAP_PDU msg)
@@ -205,8 +214,8 @@
var integer i;
log("f_ngap_ids_known(",amf_id,", ",ran_id,")");
for (i := 0; i < sizeof(NGapAssociationTable); i := i+1) {
- log("tbl[",i,"]: mme=", NGapAssociationTable[i].amf_ue_ngap_id,
- ", enb=", NGapAssociationTable[i].ran_ue_ngap_id);
+ log("tbl[",i,"]: amf=", NGapAssociationTable[i].amf_ue_ngap_id,
+ ", ran=", NGapAssociationTable[i].ran_ue_ngap_id);
/* skip empty records */
if (NGapAssociationTable[i].amf_ue_ngap_id == omit and
NGapAssociationTable[i].ran_ue_ngap_id == omit) {
@@ -214,11 +223,11 @@
continue;
}
if (NGapAssociationTable[i].amf_ue_ngap_id == omit) {
- log("entry ", i, " has no MME ID yet (enb=",
NGapAssociationTable[i].ran_ue_ngap_id);
- /* Table doesn't yet know the MME side ID, let's look-up only
+ log("entry ", i, " has no AMF ID yet (ran=",
NGapAssociationTable[i].ran_ue_ngap_id);
+ /* Table doesn't yet know the AMF side ID, let's look-up only
* based on the eNB side ID */
if (match(NGapAssociationTable[i].ran_ue_ngap_id, ran_id)) {
- /* update table with MME side ID */
+ /* update table with AMF side ID */
NGapAssociationTable[i].amf_ue_ngap_id := valueof(amf_id);
return true;
}
@@ -256,7 +265,7 @@
}
}
}
- setverdict(fail, "NGAP Association Table not found by ENB-ID=", ran_id, "
MME-ID=", amf_id);
+ setverdict(fail, "NGAP Association Table not found by RAN-ID=", ran_id, "
AMF-ID=", amf_id);
mtc.stop;
}
@@ -346,20 +355,20 @@
return mrf.msg;
}
-//function handle_NGAP_UeContextReleaseCmd(template (present) NGAP_PDU rel_cmd) runs on
NGAP_Emulation_CT {
+function handle_NGAP_UeContextReleaseCmd(template (present) NGAP_PDU rel_cmd) runs on
NGAP_Emulation_CT {
// if
(ispresent(rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_NGAP_IDs.uE_NGAP_ID_pair))
{
-// var template AMF_UE_NGAP_ID mme_ue_id;
-// var template RAN_UE_NGAP_ID enb_ue_id;
+// var template AMF_UE_NGAP_ID amf_ue_id;
+// var template RAN_UE_NGAP_ID ran_ue_id;
// var integer assoc_id;
// var NGAP_ConnHdlr vc_conn
//
-// mme_ue_id :=
rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_NGAP_IDs.uE_NGAP_ID_pair.mME_UE_NGAP_ID;
-// enb_ue_id :=
rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_NGAP_IDs.uE_NGAP_ID_pair.eNB_UE_NGAP_ID;
+// amf_ue_id :=
rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_NGAP_IDs.uE_NGAP_ID_pair.mME_UE_NGAP_ID;
+// ran_ue_id :=
rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_NGAP_IDs.uE_NGAP_ID_pair.eNB_UE_NGAP_ID;
//
-// assoc_id := f_assoc_id_by_ngap_ids(mme_ue_id, enb_ue_id);
+// assoc_id := f_assoc_id_by_ngap_ids(amf_ue_id, ran_ue_id);
// vc_conn := NGapAssociationTable[assoc_id].comp_ref;
//
-// f_ngap_id_table_del(vc_conn, valueof(enb_ue_id));
+// f_ngap_id_table_del(vc_conn, valueof(ran_ue_id));
// } else {
// /* TODO: The UE CONTEXT RELEASE COMMAND (see also: 3GPP TS 36.413, section 9.1.4.6),
may identify the
// * context by either an uE_NGAP_ID_pair (AMF_UE_NGAP_ID and RAN_UE_NGAP_ID) or an
AMF_UE_NGAP_ID alone.
@@ -367,7 +376,7 @@
// setverdict(fail, "complete implementation of UeContextReleaseCmd
handling");
// mtc.stop;
// }
-//}
+}
private function SendToNGapExpectTableProc(NGAP_PDU msg) runs on NGAP_Emulation_CT {
var integer procedureCode;
@@ -395,6 +404,19 @@
return;
}
+template ProcedureCode tr_NGAP_ProcedureCode_non_UErelated :=
+(id_NGSetup, id_RANConfigurationUpdate, id_AMFStatusIndication, id_NGReset,
id_ErrorIndication, id_OverloadStart, id_OverloadStop);
+template (present) NGAP_PDU
+tr_NGAP_nonUErelated := (mw_ngap_initMsg({procedureCode :=
tr_NGAP_ProcedureCode_non_UErelated,
+ criticality := ?,
+ value_ := ?}),
+ mw_ngap_succMsg({procedureCode := tr_NGAP_ProcedureCode_non_UErelated,
+ criticality := ?,
+ value_ := ?}),
+ mw_ngap_unsuccMsg({procedureCode := tr_NGAP_ProcedureCode_non_UErelated,
+ criticality := ?,
+ value_ := ?}));
+
function main(NGAPOps ops, NGAP_conn_parameters p, charstring id) runs on
NGAP_Emulation_CT {
var Result res;
g_pars := p;
@@ -430,7 +452,7 @@
var integer procedureCode;
var NGAP_RecvFrom mrf;
var NGAP_PDU msg;
- var charstring vlr_name, mme_name;
+ var charstring vlr_name, amf_name;
var integer ai;
var octetstring kasme;
@@ -458,54 +480,59 @@
NGAP.send(t_NGAP_Send(g_ngap_conn_id, msg));
}
- /* NGAP received from peer (MME) */
+ /* NGAP received from peer (AMF) */
[] NGAP.receive(tr_NGAP_RecvFrom_R(?)) -> value mrf {
-// if (match(mrf.msg, tr_NGAP_nonUErelated)) {
+ if (match(mrf.msg, tr_NGAP_nonUErelated)) {
/* non-UE-related NGAP message */
SendToNGapExpectTableProc(mrf.msg);
var template NGAP_PDU resp := ops.unitdata_cb.apply(mrf.msg);
if (isvalue(resp)) {
NGAP.send(t_NGAP_Send(g_ngap_conn_id, valueof(resp)));
}
-// } else {
-// /* Ue-related NGAP message */
-// /* obtain MME + ENB UE NGAP ID */
-// var template (omit) AMF_UE_NGAP_ID mme_ue_id :=
f_NGAP_get_AMF_UE_NGAP_ID(mrf.msg);
-// var template (omit) RAN_UE_NGAP_ID enb_ue_id :=
f_NGAP_get_RAN_UE_NGAP_ID(mrf.msg);
-// /* check if those IDs are known in our table */
-// if (f_ngap_ids_known(mme_ue_id, enb_ue_id)) {
-// /* if yes, dispatch to the ConnHdlr for this Ue-Connection */
-// var template (omit) octetstring nas_enc;
-// var integer assoc_id := f_assoc_id_by_ngap_ids(mme_ue_id, enb_ue_id);
-// vc_conn := NGapAssociationTable[assoc_id].comp_ref;
-// nas_enc := f_NGAP_get_NAS_PDU(mrf.msg);
-// if (isvalue(nas_enc)) {
-// nas := dec_PDU_NAS_EPS(valueof(nas_enc));
-// if (match(nas, tr_NAS_EMM_SecurityProtected)) {
-// nas := f_nas_try_decaps(NGapAssociationTable[assoc_id].nus, nas);
-// }
-// /* DL/UlNasTransport are not interesting, don't send them */
-// if (not match(mrf.msg, (tr_NGAP_DlNasTransport, tr_NGAP_UlNasTransport))) {
-// /* send raw NGAP */
-// NGAP_CLIENT.send(mrf.msg) to vc_conn;
-// }
-// /* send decoded NAS */
-// NGAP_CLIENT.send(nas) to vc_conn;
-// } else {
-// /* send raw NGAP */
-// NGAP_CLIENT.send(mrf.msg) to vc_conn;
-// }
-// } else {
-// /* if not, call create_cb so it can create new ConnHdlr */
-// vc_conn := ops.create_cb.apply(mrf.msg, mme_ue_id, enb_ue_id, id);
-// f_ngap_id_table_add(vc_conn, mme_ue_id, valueof(enb_ue_id));
-// NGAP_CLIENT.send(mrf.msg) to vc_conn;
-// }
-// if (match(mrf.msg, tr_NGAP_UeContextReleaseCmd)) {
-// handle_NGAP_UeContextReleaseCmd(mrf.msg);
-// }
-// }
+ } else {
+ /* Ue-related NGAP message */
+ /* obtain AMF + NGRAN UE NGAP ID */
+ var template (omit) AMF_UE_NGAP_ID amf_ue_id := f_NGAP_get_AMF_UE_NGAP_ID(mrf.msg);
+ var template (omit) RAN_UE_NGAP_ID ran_ue_id := f_NGAP_get_RAN_UE_NGAP_ID(mrf.msg);
+ /* check if those IDs are known in our table */
+ if (f_ngap_ids_known(amf_ue_id, ran_ue_id)) {
+ /* if yes, dispatch to the ConnHdlr for this Ue-Connection */
+ var template (omit) octetstring nas_enc;
+ var integer assoc_id := f_assoc_id_by_ngap_ids(amf_ue_id, ran_ue_id);
+ vc_conn := NGapAssociationTable[assoc_id].comp_ref;
+ nas_enc := f_NGAP_get_NAS_PDU(mrf.msg);
+ if (isvalue(nas_enc)) {
+ if (g_pars.role == NGAP_NAS_ROLE_UE) {
+ var NG_NAS_DL_Message_Type dl_nas :=
dec_NG_NAS_DL_Message_Type(valueof(nas_enc));
+// if (match(dl_nas, tr_NAS_EMM_SecurityProtected)) {
+// dl_nas := f_nas_try_decaps(NGapAssociationTable[assoc_id].nus, dl_nas);
+// }
+ /* DL/UlNasTransport are not interesting, don't send them */
+ if (not match(mrf.msg, mw_ngap_initMsg(mw_n2_DownlinkNASTransport))) {
+ /* send raw NGAP */
+ NGAP_CLIENT.send(mrf.msg) to vc_conn;
+ }
+ /* send decoded NAS */
+ NGAP_CLIENT.send(dl_nas) to vc_conn;
+ } else {
+ log("Incoming NAS HANDLING in AMF role not supported!");
+ var NG_NAS_UL_Message_Type ul_nas :=
dec_NG_NAS_UL_Message_Type(valueof(nas_enc));
+ }
+ } else {
+ /* send raw NGAP */
+ NGAP_CLIENT.send(mrf.msg) to vc_conn;
+ }
+ } else {
+ /* if not, call create_cb so it can create new ConnHdlr */
+ vc_conn := ops.create_cb.apply(mrf.msg, amf_ue_id, ran_ue_id, id);
+ f_ngap_id_table_add(vc_conn, amf_ue_id, valueof(ran_ue_id));
+ NGAP_CLIENT.send(mrf.msg) to vc_conn;
+ }
+ if (match(mrf.msg, mw_ngap_initMsg(mw_n2_UEContextReleaseCommand))) {
+ handle_NGAP_UeContextReleaseCmd(mrf.msg);
+ }
}
+ }
[] NGAP.receive(tr_SctpAssocChange) { }
[] NGAP.receive(tr_SctpPeerAddrChange) { }
[] NGAP_PROC.getcall(NGAPEM_register:{?,?,?}) -> param(amf_id, ran_id, vc_conn) {
diff --git a/library/NGAP_Functions.ttcn b/library/NGAP_Functions.ttcn
index 7ab2f5a..1323ab9 100644
--- a/library/NGAP_Functions.ttcn
+++ b/library/NGAP_Functions.ttcn
@@ -21,7 +21,10 @@
{
if (ischosen(ngap.initiatingMessage)) {
var InitiatingMessage im := ngap.initiatingMessage;
- select (ngap) {
+ select (im) {
+ case (mw_n2_DownlinkNASTransport) {
+ return im.value_.downlinkNASTransport.protocolIEs[0].value_.aMF_UE_NGAP_ID;
+ }
case (?) {
return omit;
/* TODO */
@@ -31,7 +34,7 @@
}
} else if (ischosen(ngap.successfulOutcome)) {
var SuccessfulOutcome so := ngap.successfulOutcome;
- select (ngap) {
+ select (so) {
case (?) {
return omit;
/* TODO */
@@ -41,7 +44,7 @@
}
} else if (ischosen(ngap.unsuccessfulOutcome)) {
var UnsuccessfulOutcome uo := ngap.unsuccessfulOutcome;
- select (ngap) {
+ select (uo) {
case (?) {
return omit;
/* TODO */
@@ -61,11 +64,14 @@
case (mw_n2_initialUeMessage) {
return im.value_.InitialUEMessage.protocolIEs[0].value_.RAN_UE_NGAP_ID;
}
+ case (mw_n2_DownlinkNASTransport) {
+ return im.value_.downlinkNASTransport.protocolIEs[1].value_.RAN_UE_NGAP_ID;
+ }
/* TODO */
}
} else if (ischosen(ngap.successfulOutcome)) {
var SuccessfulOutcome so := ngap.successfulOutcome;
- select (ngap) {
+ select (so) {
case (?) {
return omit;
/* TODO */
@@ -75,7 +81,7 @@
}
} else if (ischosen(ngap.unsuccessfulOutcome)) {
var UnsuccessfulOutcome uo := ngap.unsuccessfulOutcome;
- select (ngap) {
+ select (uo) {
case (?) {
return omit;
/* TODO */
@@ -87,4 +93,41 @@
return omit;
}
+function f_NGAP_get_NAS_PDU(NGAP_PDU ngap) return template (omit) NAS_PDU
+{
+ var integer i, j;
+
+ if (ischosen(ngap.initiatingMessage)) {
+ var InitiatingMessage im := ngap.initiatingMessage;
+ select (im) {
+ case (mw_n2_DownlinkNASTransport) {
+ var DownlinkNASTransport msg := im.value_.DownlinkNASTransport;
+ for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) {
+ if (msg.protocolIEs[i].id == id_NAS_PDU) {
+ return msg.protocolIEs[i].value_.NAS_PDU;
+ }
+ }
+ }
+ case (mw_n2_UplinkNASTransport) {
+ var UplinkNASTransport msg := im.value_.UplinkNASTransport;
+ for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) {
+ if (msg.protocolIEs[i].id == id_NAS_PDU) {
+ return msg.protocolIEs[i].value_.NAS_PDU;
+ }
+ }
+ }
+ case (mw_n2_initialUeMessage) {
+ var InitialUEMessage msg := im.value_.InitialUEMessage;
+ for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) {
+ if (msg.protocolIEs[i].id == id_NAS_PDU) {
+ return msg.protocolIEs[i].value_.NAS_PDU;
+ }
+ }
+ return omit;
+ }
+ }
+ }
+ return omit;
+}
+
}
diff --git a/library/NG_NAS_Osmo_Templates.ttcn b/library/NG_NAS_Osmo_Templates.ttcn
new file mode 100644
index 0000000..a22c542
--- /dev/null
+++ b/library/NG_NAS_Osmo_Templates.ttcn
@@ -0,0 +1,71 @@
+/* Our own NG NAS templates on top of deps/nas/ttcn/Lib3GPP/NG_NAS/NG_NAS_Templates.ttcn.
*/
+module NG_NAS_Osmo_Templates {
+
+/* (C) 2025 by sysmocom - s.f.m.c. GmbH <info(a)sysmocom.de>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+import from CommonDefs all;
+import from NAS_CommonTypeDefs all;
+import from NAS_CommonTemplates all;
+import from NG_NAS_Common all;
+import from NG_NAS_TypeDefs all;
+import from NG_NAS_Templates all;
+import from NG_NAS_MsgContainers all;
+
+/* 24.501 cl. 9.11.3.54 */
+private function f_cs_NG_UE_SecurityCapability_length(template (omit) O1_Type eeaCap :=
omit,
+ template (omit) O1_Type eiaCap := omit)
+return integer {
+ var integer len := 2;
+ if (isvalue(eeaCap)) {
+ len := len + 1;
+ }
+ if (isvalue(eiaCap)) {
+ len := len + 1;
+ }
+ return len;
+}
+template (value) NG_UE_SecurityCapability cs_NG_UE_SecurityCapability(template (value)
O1_Type ngeaCap := 'f0'O,
+ template (value) O1_Type ngiaCap := '70'O,
+ template (omit) O1_Type eeaCap := omit,
+ template (omit) O1_Type eiaCap := omit) :=
+{
+ iei := '2E'O,
+ iel := int2oct(f_cs_NG_UE_SecurityCapability_length(eeaCap, eiaCap), 1),
+ ngeaCap := ngeaCap,
+ ngiaCap := ngiaCap,
+ eeaCap := eeaCap,
+ eiaCap := eiaCap,
+ spare := omit
+};
+
+
+/* 24.501 cl. 8.2.1 */
+template (present) NG_NAS_DL_Message_Type cr_NG_AUTHENTICATION_REQUEST(template (present)
NAS_KsiValue p_KeySetId := ?,
+ template (present) ABBA p_ABBA := ?,
+ template RAND p_RAND := *,
+ template AUTN p_AUTN := *,
+ template EAP_Message p_EAP := *
+ ) :=
+{ /* 24.501 cl. 8.2.1 */
+ authentication_Request := {
+ protocolDiscriminator := tsc_EPD_GMM, /* cl. 9.2 M V 1
*/
+ spareHalfOctet := tsc_SpareHalfOctet, /* cl. 9.3 M V 1/2 */
+ securityHeaderType := tsc_SHT_NoSecurityProtection,
+ messageType := tsc_MT_NG_AuthenticationRequest, /* cl. 9.7 M V 1 */
+ spareHalfOctet2 := tsc_SpareHalfOctet, /* cl. 9.5 M V 1/2 */
+ ngNasKeySetId := cr_NAS_KeySetIdentifier(p_KeySetId,
tsc_NasKsi_NativeSecurityContext), /* cl. 9.11.3.32 M V 1/2 */
+ abba := p_ABBA, /* cl. 9.11.3.10 M LV 3-n
*/
+ rand := p_RAND, /* cl. 9.11.3.16 O TV 17
IEI=21 */
+ autn := p_AUTN, /* cl. 9.11.3.15 O TLV 18
IEI=20 */
+ eapMessage := p_EAP /* cl. 9.11.2.2 O TLV-E
7-1503 IEI=78 */
+ }
+}
+
+}
diff --git a/library/Osmocom_Types.ttcn b/library/Osmocom_Types.ttcn
index 995342a..21d7abf 100644
--- a/library/Osmocom_Types.ttcn
+++ b/library/Osmocom_Types.ttcn
@@ -343,7 +343,7 @@
}
-private function f_concat_pad(integer tot_len, hexstring prefix, integer suffix) return
hexstring {
+function f_concat_pad(integer tot_len, hexstring prefix, integer suffix) return hexstring
{
var integer suffix_len := tot_len - lengthof(prefix);
var charstring suffix_ch := int2str(suffix);
var integer pad_len := suffix_len - lengthof(suffix_ch);
--
To view, visit
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/40408?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I6697f30f95777fc9aed16a529a669d10f42c57be
Gerrit-Change-Number: 40408
Gerrit-PatchSet: 4
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>