pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/40445?usp=email )
Change subject: 5gc: Support PDU Session Establishment procedure ......................................................................
5gc: Support PDU Session Establishment procedure
This commit adds initial support to issue a successful PDU Session Establishment procedure towards the 5GC, getting a ready-to-use GTPU session with IPv4 addr + TEID + UE IP address.
commit has to our nas.git fork is updated in order to have multiple fixes and improvements needed to have everything working fine.
Related: SYS#7073 Change-Id: If0769afd07a4bae7778d7a7c347cebaa5909b5f8 --- M 5gc/C5G_Tests.ttcn M 5gc/gen_links.sh M deps/Makefile M library/NGAP_Functions.ttcn M library/NG_NAS_Functions.ttcn M library/NG_NAS_Osmo_Templates.ttcn A library/NG_NAS_Osmo_Types.ttcn M library/ngap/NGAP_EncDec.cc M library/ngap/NGAP_Templates.ttcn M library/ngap/NGAP_Types.ttcn 10 files changed, 490 insertions(+), 12 deletions(-)
Approvals: pespin: Looks good to me, approved Jenkins Builder: Verified jolly: Looks good to me, but someone else must approve
diff --git a/5gc/C5G_Tests.ttcn b/5gc/C5G_Tests.ttcn index cd7007b..f5b0931 100644 --- a/5gc/C5G_Tests.ttcn +++ b/5gc/C5G_Tests.ttcn @@ -19,6 +19,8 @@ import from Osmocom_Types all; import from GSM_Types all;
+import from DNS_Helpers all; + import from Milenage_Functions all;
import from NGAP_PDU_Descriptions all; @@ -62,6 +64,8 @@ octetstring mp_usim_key := '762a2206fe0b4151ace403c86a11e479'O; octetstring mp_usim_opc := '3c6e0b8a9c15224a8228b9a98ca1531d'O; uint24_t mp_tac := 1; + charstring mp_apn := "internet"; + charstring mp_local_gtpu_ip := "127.0.0.1"; }
/* parameters of emulated gNB / ng-eNB */ @@ -77,7 +81,11 @@ HEX16n imeisv, octetstring usim_key, octetstring usim_opc, - charstring ue_ip, + charstring ran_gtpu_ip, + OCT4 ran_gtpu_teid, + charstring cn_gtpu_ip optional, + OCT4 cn_gtpu_teid optional, + charstring ue_ip optional, OCT32 kausf optional, OCT32 kseaf optional, OCT32 kamf optional @@ -89,7 +97,11 @@ imeisv := f_rnd_imeisv(), usim_key := mp_usim_key, usim_opc := mp_usim_opc, - ue_ip := "192.168.123.50", + ran_gtpu_ip := mp_local_gtpu_ip, + ran_gtpu_teid := int2oct(imsi_suffix, 4), + cn_gtpu_ip := omit, + cn_gtpu_teid := omit, + ue_ip := omit, kausf := omit, kseaf := omit, kamf := omit @@ -321,7 +333,6 @@ 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); var integer ret; var integer my_sqn := 0; /* TODO: move to a ConnHdlr state attribute? */ var OCT16 rand := bit2oct(rx_nas.authentication_Request.rand.randValue); @@ -383,7 +394,6 @@ ngiaCap := '40'O /* ONLY NIA1 supported */);
[] NGAP.receive(cr_NG_SECURITY_MODE_COMMAND(p_UECap := ue_sec_cap)) -> value rx_nas { - log("Rx inner NAS: ", rx_nas); /* Configure integrity protection: */ cfg := { set_nas_alg_int := NG_NAS_ALG_IP_NIA1 @@ -417,6 +427,99 @@ } }
+/* Handle a PDUSessionResourceSetupRequestTransfer contained inside NGAP InitialContextSetupRequest and return a Result for InitialContextSetupResponse */ +private function f_pdu_handle_session_resource_setup_item(PDUSessionResourceSetupItemCxtReq req) runs on ConnHdlr return PDUSessionResourceSetupItemCxtRes +{ + var PDUSessionResourceSetupItemCxtRes resp; + var octetstring setup_trans_enc; + var NGAP_IEs.PDUSessionResourceSetupRequestTransfer setup_req_transf; + var NGAP_IEs.PDUSessionResourceSetupResponseTransfer setup_resp_transf; + var template (value) UPTransportLayerInformation utla; + var template (value) QosFlowPerTNLInformation qos; + + /* Parse PDUSessionResourceSetupRequestTransfer contained inside InitialContextSetupRequest's PDUSessionResourceSetup Item: */ + setup_req_transf := dec_NGAP_PDUSessionResourceSetupRequestTransfer(req.pDUSessionResourceSetupRequestTransfer); + for (var integer i := 0; i < lengthof(setup_req_transf.protocolIEs); i := i + 1) { + if (setup_req_transf.protocolIEs[i].id == id_UL_NGU_UP_TNLInformation) { + var UPTransportLayerInformation utli := setup_req_transf.protocolIEs[i].value_.uPTransportLayerInformation; + g_pars.ue_pars.cn_gtpu_ip := f_inet_ntoa(bit2oct(utli.gTPTunnel.transportLayerAddress)); + g_pars.ue_pars.cn_gtpu_teid := utli.gTPTunnel.gTP_TEID; + } + } + + /* Prepare Response for it: */ + utla := m_uPTransportLayerInformation_gTPTunnel( + m_gTPTunnel(p_tla := oct2bit(f_inet_addr(g_pars.ue_pars.ran_gtpu_ip)), + p_gtp_teid := g_pars.ue_pars.ran_gtpu_teid)); + qos := m_qosFlowPerTNLInformation(utla, { m_associatedQosFlowItem(1) }); + setup_resp_transf := valueof(m_pDUSessionResourceSetupResponseTransfer(qos)); + setup_trans_enc := enc_NGAP_PDUSessionResourceSetupResponseTransfer(setup_resp_transf) + resp := valueof(m_pDUSessionResourceSetupItemCxtRes(req.pDUSessionID, setup_trans_enc)); + return resp; +} + +private function f_pdu_handle_session_resource_setup_list(PDUSessionResourceSetupListCxtReq li_req) runs on ConnHdlr return PDUSessionResourceSetupListCxtRes +{ + var PDUSessionResourceSetupListCxtRes li_resp; + for (var integer i := 0; i < lengthof(li_req); i := i + 1) { + var PDUSessionResourceSetupItemCxtRes it_resp; + it_resp := f_pdu_handle_session_resource_setup_item(li_req[i]); + if (i == 0) { /* min 1 item in list doesn't allow previously allocating an empty list */ + li_resp := { it_resp }; + } else { + li_resp := li_resp & { it_resp }; + } + } + return li_resp; +} + +private altstep as_ngap_handle_InitialCtxReq_withPDUSessionList() runs on ConnHdlr { + var NGAP_PDU rx_ngap; + + [] NGAP.receive(mw_ngap_initMsg(mw_n2_InitialContextSetupRequest_withPDUSessionList)) -> value rx_ngap { + var AMF_UE_NGAP_ID amf_id := valueof(f_NGAP_get_AMF_UE_NGAP_ID(rx_ngap)); + var RAN_UE_NGAP_ID ran_id := valueof(f_NGAP_get_RAN_UE_NGAP_ID(rx_ngap)); + var InitialContextSetupRequest ctx_setup_req := rx_ngap.initiatingMessage.value_.initialContextSetupRequest; + var PDUSessionResourceSetupListCxtRes resources; + + for (var integer i := 0; i < lengthof(ctx_setup_req.protocolIEs); i := i + 1) { + if (ctx_setup_req.protocolIEs[i].id != id_PDUSessionResourceSetupListCxtReq) { + continue; + } + var PDUSessionResourceSetupListCxtReq li := ctx_setup_req.protocolIEs[i].value_.pDUSessionResourceSetupListCxtReq; + resources := f_pdu_handle_session_resource_setup_list(li); + } + NGAP.send(m_ngap_succMsg(m_n2_InitialContextSetupResponse(amf_id, ran_id, resources))); + } +} + +private function f_pdu_sess_establish() runs on ConnHdlr { + var template (value) NG_NAS_UL_Message_Type nas_ul_msg; + var NAS_PDU nas_pdu; + var NG_NAS_DL_Message_Type rx_nas, inner_nas; + + nas_ul_msg := cs_NG_PDU_SESSION_ESTABLISHMENT_REQUEST(cs_NG_PDU_SessionIdV('01'O), '01'O, + p_IntegrityProtMaxDataRate := cs_IntegrityProtMaxDataRateV('FF'O, 'FF'O), + p_PDU_SessionType := cs_PDU_SessionTypeTV('001'B), /* IPv4 */ + p_SSC_Mode := cs_SSC_ModeTV('001'B)); + nas_pdu := enc_NG_NAS_UL_Message_Type(valueof(nas_ul_msg)); + nas_ul_msg := cs_NG_UL_NAS_TRANSPORT(cs_PayloadContainerType(tsc_PayloadContainerESMMsg), + cs_PayloadContainerLV(nas_pdu), + p_PDU_SessionId := cs_NG_PDU_SessionIdTV('01'O), + p_RequestType := cs_NG_Request_TypeTV('001'B), + p_DNN := cs_DNN_TLV(f_enc_dns_hostname(mp_apn))); + NGAP.send(nas_ul_msg); + as_ngap_handle_InitialCtxReq_withPDUSessionList(); + + /* PDU Session Establishment Accept: This DL NAS arrives contained in InitialCtxReq handled above: */ + NGAP.receive(cr_NG_DL_NAS_TRANSPORT) -> value rx_nas; + inner_nas := f_dec_NG_NAS_DL_Message_Payload_Container(rx_nas.dl_Nas_Transport.payloadContainerType.container, + rx_nas.dl_Nas_Transport.payload.payload); + g_pars.ue_pars.ue_ip := f_inet_ntoa(inner_nas.pdu_Session_Establishment_Accept.pduAddress.adressInfo); + log("5GC assigned CN GTPU Address: ", g_pars.ue_pars.cn_gtpu_ip, " TEID: ", g_pars.ue_pars.cn_gtpu_teid); + log("5GC assigned UE IP address: ", g_pars.ue_pars.ue_ip); +} + private function f_register() runs on ConnHdlr { var template (value) NGAP_PDU tx_pdu; var template (value) NG_NAS_UL_Message_Type nas_ul_msg; @@ -454,8 +557,7 @@
as_ngap_handle_configuration_update();
- /* TODO: PDU session establishment request */ - f_sleep(5.0); + f_pdu_sess_establish(); }
/* NG Setup procedure to 5GC using a Global gNB ID containing unknown/foreign PLMN. diff --git a/5gc/gen_links.sh b/5gc/gen_links.sh index ee09250..43a679b 100755 --- a/5gc/gen_links.sh +++ b/5gc/gen_links.sh @@ -78,7 +78,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_Osmo_Templates.ttcn NG_NAS_Functions.ttcn " +FILES+="NG_NAS_Osmo_Types.ttcn NG_NAS_Osmo_Templates.ttcn NG_NAS_Functions.ttcn " FILES+="NG_CryptoFunctionDefs.cc NG_CryptoFunctions.ttcn " gen_links $DIR $FILES
diff --git a/deps/Makefile b/deps/Makefile index 8739abc..0f710e8 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -72,7 +72,7 @@
# Use tag names from 'git describe --tags' or commit hashes. This way we get # exact commits of deps when doing regression testing. -nas_commit= eff069b772a53e16773638f07599e7936ffcdd9a +nas_commit= 320d388e3aaee6c4f81488e6b5a8a27e7947b690 titan.Libraries.TCCUsefulFunctions_commit= R.35.B-6-gb3687da titan.ProtocolEmulations.M3UA_commit= b58f92046e48a7b1ed531e243a2319ebca53bf4c titan.ProtocolEmulations.SCCP_commit= 750a3e836831e58eae59d4757ef5d0c759f9ca5d diff --git a/library/NGAP_Functions.ttcn b/library/NGAP_Functions.ttcn index 523754e..f6c1389 100644 --- a/library/NGAP_Functions.ttcn +++ b/library/NGAP_Functions.ttcn @@ -25,6 +25,9 @@ case (id_DownlinkNASTransport) { return im.value_.downlinkNASTransport.protocolIEs[0].value_.aMF_UE_NGAP_ID; } + case (id_InitialContextSetup) { + return im.value_.initialContextSetupRequest.protocolIEs[0].value_.aMF_UE_NGAP_ID; + } case (id_UEContextRelease) { return im.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_NGAP_IDs.uE_NGAP_ID_pair.aMF_UE_NGAP_ID; } @@ -65,8 +68,11 @@ case (id_DownlinkNASTransport) { return im.value_.downlinkNASTransport.protocolIEs[1].value_.RAN_UE_NGAP_ID; } + case (id_InitialContextSetup) { + return im.value_.initialContextSetupRequest.protocolIEs[1].value_.RAN_UE_NGAP_ID; + } case (id_UEContextRelease) { - return im.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_NGAP_IDs.uE_NGAP_ID_pair.rAN_UE_NGAP_ID; + return im.value_.uEContextReleaseCommand.protocolIEs[1].value_.uE_NGAP_IDs.uE_NGAP_ID_pair.rAN_UE_NGAP_ID; } /* TODO */ } @@ -126,6 +132,19 @@ } return omit; } + case (id_InitialContextSetup) { + var InitialContextSetupRequest msg := im.value_.initialContextSetupRequest; + for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) { + if (msg.protocolIEs[i].id == id_PDUSessionResourceSetupListCxtReq) { + var PDUSessionResourceSetupListCxtReq req_li := msg.protocolIEs[i].value_.pDUSessionResourceSetupListCxtReq; + for (j := 0; j < lengthof(req_li); j := j+1) { + return req_li[j].nAS_PDU; + /* FIXME: we should be returning req_li[j].pDUSessionResourceSetupRequestTransfer too... */ + } + } + } + return omit; + } } } return omit; diff --git a/library/NG_NAS_Functions.ttcn b/library/NG_NAS_Functions.ttcn index 4f0e4da..0fbfa75 100644 --- a/library/NG_NAS_Functions.ttcn +++ b/library/NG_NAS_Functions.ttcn @@ -13,16 +13,67 @@ import from NG_NAS_TypeDefs all; import from EAP_TypeDefs all;
+import from General_Types all; +import from Misc_Helpers all; + +import from NG_NAS_Osmo_Types all; + external function enc_NG_NAS_UL_Message_Type(in NG_NAS_UL_Message_Type pdu) return octetstring with { extension "prototype(convert)" extension "encode(RAW)" } - external function dec_NG_NAS_UL_Message_Type(in octetstring stream) return NG_NAS_UL_Message_Type with { extension "prototype(convert)" extension "decode(RAW)" }
external function enc_NG_NAS_DL_Message_Type(in NG_NAS_DL_Message_Type pdu) return octetstring with { extension "prototype(convert)" extension "encode(RAW)" } - external function dec_NG_NAS_DL_Message_Type(in octetstring stream) return NG_NAS_DL_Message_Type with { extension "prototype(convert)" extension "decode(RAW)" }
+external function enc_NG_NAS_DL_SM_Message_Type(in NG_NAS_DL_SM_Message_Type pdu) return octetstring +with { extension "prototype(convert)" extension "encode(RAW)" } +external function dec_NG_NAS_DL_SM_Message_Type(in octetstring stream) return NG_NAS_DL_SM_Message_Type +with { extension "prototype(convert)" extension "decode(RAW)" } + + +/* Decode 3GPP TS 24.501 9.11.3.39 Payload container based on 9.11.3.40 Payload container type. + * Trying to decode it directly through dec_NG_NAS_DL_Message_Type() may end up with unexpected + * union choice due to circumstancial match in previous field securityHeaderType. + * pct = PayloadContainerType.container, payload = PayloadContainer.payload + */ +function f_dec_NG_NAS_DL_Message_Payload_Container(BIT4 pct, octetstring payload) return NG_NAS_DL_Message_Type +{ + var NG_NAS_DL_Message_Type ret; + select (pct) { + case (c_PayloadContainer_N1_SM_Info) { + var NG_NAS_DL_SM_Message_Type sm := dec_NG_NAS_DL_SM_Message_Type(payload); + if (ischosen(sm.pdu_Session_Authentication_Command)) { + ret.pdu_Session_Authentication_Command := sm.pdu_Session_Authentication_Command; + } else if (ischosen(sm.pdu_Session_Authentication_Result)) { + ret.pdu_Session_Authentication_Result := sm.pdu_Session_Authentication_Result; + } else if (ischosen(sm.pdu_Session_Establishment_Accept)) { + ret.pdu_Session_Establishment_Accept := sm.pdu_Session_Establishment_Accept; + } else if (ischosen(sm.pdu_Session_Establishment_Reject)) { + ret.pdu_Session_Establishment_Reject := sm.pdu_Session_Establishment_Reject; + } else if (ischosen(sm.pdu_Session_Modification_Command)) { + ret.pdu_Session_Modification_Command := sm.pdu_Session_Modification_Command; + } else if (ischosen(sm.pdu_Session_Modification_Reject)) { + ret.pdu_Session_Release_Command := sm.pdu_Session_Release_Command; + } else if (ischosen(sm.pdu_Session_Release_Reject)) { + ret.pdu_Session_Release_Reject := sm.pdu_Session_Release_Reject; + } else if (ischosen(sm.gsm_Status)) { + ret.gsm_Status := sm.gsm_Status; + } else { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + log2str("Unexpected decoded Payload Container ", sm)); + } + return ret; + } + case else { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + log2str("Unimplemented decoding of Payload Container Type ", + pct, ", Payload Container ", payload)); + } + } + return ret; +} + } diff --git a/library/NG_NAS_Osmo_Templates.ttcn b/library/NG_NAS_Osmo_Templates.ttcn index 9e61249..f417fcc 100644 --- a/library/NG_NAS_Osmo_Templates.ttcn +++ b/library/NG_NAS_Osmo_Templates.ttcn @@ -101,6 +101,75 @@ resultValue := p_Result };
+/* 24.501 cl. 9.11.3.21 */ +template (value) DNN +cs_DNN_TLV(template (value) octetstring p_DNN) := +{ + iei := '25'O, + iel := '00'O, /* overwritten by RAW encoder */ + dnnValue := p_DNN +}; + +/* 24.501 cl. 9.11.3.39 */ +template (value) PayloadContainer +cs_PayloadContainerLV(octetstring p_EncodedGSMMsg) := +{ + iei := omit, + iel := '0000'O, /* overwritten by RAW encoder */ + payload := p_EncodedGSMMsg +}; + +/* 24.501 cl. 9.11.3.41 */ +template (value) NG_PDU_SessionId +cs_NG_PDU_SessionIdV(template (value) O1_Type p_Id := '00'O) := // @sic R5s190338 sic@ +{ + iei := omit, + sessionId := p_Id +}; +template (value) NG_PDU_SessionId +cs_NG_PDU_SessionIdTV(template (value) O1_Type p_Id := '00'O) := // @sic R5s190338 sic@ +{ + iei := '12'O, + sessionId := p_Id +}; + +/* 24.501 cl. 9.11.3.47 */ +template (value) NG_Request_Type cs_NG_Request_TypeTV(B3_Type p_RequestValue) := +{ + iei := '8'H, + spare := tsc_Spare1, + requestValue := p_RequestValue +}; + + +/* 24.501 cl. 9.11.4.7 */ +template (value) IntegrityProtMaxDataRate +cs_IntegrityProtMaxDataRateV(template (value) O1_Type maxDataRateUL, + template (value) O1_Type maxDataRateD) := +{ + iei := omit, + maxDataRateUL := maxDataRateUL, + maxDataRateDL := maxDataRateD +}; + +/* 24.501 cl. 9.11.4.11 */ +template (value) PDU_SessionType +cs_PDU_SessionTypeTV(template (value) B3_Type p_Type) := +{ + iei := '9'H, + spare := tsc_Spare1, + typeValue := p_Type +}; + +/* 24.501 cl. 9.11.4.16 */ +template (value) SSC_Mode +cs_SSC_ModeTV(B3_Type p_SSCMode) := +{ + iei := 'A'H, + spare := tsc_Spare1, + sscModeValue := p_SSCMode +}; + /* 24.501 cl. 8.2.1 */ template (present) NG_NAS_DL_Message_Type cr_NG_AUTHENTICATION_REQUEST(template (present) NAS_KsiValue p_KeySetId := ?, @@ -278,6 +347,64 @@ } }
+/* 24.501 cl. 8.2.10 */ +template (value) NG_NAS_UL_Message_Type +cs_NG_UL_NAS_TRANSPORT(template (value) PayloadContainerType p_PayloadContainerType, + template (value) PayloadContainer p_PayloadContainer, + template (omit) NG_PDU_SessionId p_PDU_SessionId := omit, + template (omit) NG_PDU_SessionId p_OldPDU_SessionId := omit, + template (omit) NG_Request_Type p_RequestType := omit, + template (omit) S_NSSAI_Type p_S_NSSAI := omit, + template (omit) DNN p_DNN := omit, + template (omit) AdditionalInformation p_AdditionalInfo := omit, + template (omit) MA_PDUSessionInfo p_MA_PDUSessionInfo := omit, + template (omit) ReleaseAssistanceInd p_ReleaseAssistanceInd := omit) := +{ + ul_Nas_Transport := { + 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_UL_NASTransport, /* cl. 9.7 M V 1 */ + spareHalfOctet2 := tsc_SpareHalfOctet, /* cl. 9.5 M V 1/2 */ + payloadContainerType := p_PayloadContainerType, /* cl. 9.11.3.40 M V 1/2 */ + payload := p_PayloadContainer, /* cl. 9.11.3.39 M LV-E 3-65537 */ + pduSessionId := p_PDU_SessionId, /* cl. 9.11.3.41 C TV 2 IEI=70 */ + oldPDUSessionId := p_OldPDU_SessionId, /* cl. 9.11.3.41 O TV 3 IEI=61 */ + requestType := p_RequestType, /* cl. 9.`0.3.47 O TV 1 IEI=8 */ + s_NSSAI := p_S_NSSAI, /* cl. 9.11.2.8 O TLV 3-10 IEI=22 */ + dnn := p_DNN, /* cl. 9.11.3.21 O TLV 3-102 IEI=25 */ + additionalInfo := p_AdditionalInfo, /* cl. 9.11.2.1 O TLV 3-n IEI=24 */ + maPDUSessionInfo := p_MA_PDUSessionInfo, /* cl. 9.11.3.31A O TV 1 IEI=A Sep20 @sic R5s201387 Baseline Moving sic@ */ + releaseAssistanceInd := p_ReleaseAssistanceInd /* cl. 9.11.3.46A O TV 1 IEI=F Sep20 @sic R5s201387 Baseline Moving sic@ */ + } +} + +/* 24.501 cl. 8.2.11 */ +template (present) NG_NAS_DL_Message_Type +cr_NG_DL_NAS_TRANSPORT(template (present) PayloadContainerType p_PayloadContainerType := ?, + template (present) PayloadContainer p_Payload := ?, + template NG_PDU_SessionId p_PDU_SessionId := *, + template AdditionalInformation p_AdditionalInfo := *, + template GMM_GSM_Cause p_Cause := *, + template GPRS_Timer3 p_BackOff := *, + template GPRS_Timer3 p_LowerBoundTimerValue := *) := +{ + dl_Nas_Transport := { + 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_DL_NASTransport, /* cl. 9.7 M V 1 */ + spareHalfOctet2 := tsc_SpareHalfOctet, /* cl. 9.5 M V 1/2 */ + payloadContainerType := p_PayloadContainerType, /* cl. 9.11.3.40 M V 1/2 */ + payload := p_Payload, /* cl. 9.11.3.39 M LV-E 3-65537 */ + pduSessionId := p_PDU_SessionId, /* cl. 9.11.3.41 C TV 2 IEI=70 */ + additionalInfo := p_AdditionalInfo, /* cl. 9.11.2.1 O TLV 3-n IEI=24 */ + gmmCause := p_Cause, /* cl. 9.11.3.2 O TV 2 IEI=58 */ + backOffTimerValue := p_BackOff, /* cl. 9.11.2.5 O TLV 3 IEI=37 */ + lowerBoundTimerValue := p_LowerBoundTimerValue /* cl. 9.11.2.5 O TLV 3 IEI=3A Sep22 @sic R5s221179 Baseline Moving sic@ */ + } +} + /* 24.501 cl. 8.2.19 */ template (present) NG_NAS_DL_Message_Type cr_NG_CONFIGURATION_UPDATE_COMMAND(template ConfigUpdateInd p_ConfigUpdateInd := *, @@ -453,4 +580,52 @@ } }
+/* 24.501 cl. 8.3.1 */ +template (value) NG_NAS_UL_Message_Type +cs_NG_PDU_SESSION_ESTABLISHMENT_REQUEST(template (value) NG_PDU_SessionId p_PDU_SessionId, + template (value) ProcedureTransactionIdentifier p_PTI, + template (omit) IntegrityProtMaxDataRate p_IntegrityProtMaxDataRate := omit, + template (omit) PDU_SessionType p_PDU_SessionType := omit, + template (omit) SSC_Mode p_SSC_Mode := omit, + template (omit) NG_UE_SM_Cap p_UECap := omit, + template (omit) MaxNumPacketFilters p_MaxNumPacketFilters := omit, + template (omit) AlwaysOnPDUSessionReq p_AlwaysOnPDUSessionReq := omit, + template (omit) SM_PDU_DN_RequestContainer p_PDUReq := omit, + template (omit) ExtdProtocolConfigOptions p_ExtdPCO := omit, + template (omit) IPHeaderCompressionConfig p_IPHeaderCompConfig := omit, + template (omit) DS_TT_EthernetPortMACAddr p_DS_TT_EthernetPortMACAddr := omit, + template (omit) UE_DS_TT_ResidenceTime p_UE_DS_TT_ResidenceTime := omit, + template (omit) PortManagementInfoContainer p_PortManagementInfoContainer := omit, + template (omit) EthernetHeaderCompressConfig p_EthernetHeaderCompConfig := omit, + template (omit) PDU_Address p_SuggestedInterfaceId := omit, + template (omit) ServiceLvlAAContainer p_ServiceLvlAA := omit, + template (omit) RequestedMBSContainer p_RequestedMBS := omit, + template (omit) PDUSessionPairId p_PduSessionPairId := omit, + template (omit) RSN p_RSN := omit) := { + pdu_Session_Establishment_Request := { + protocolDiscriminator := tsc_EPD_GSM, /* cl. 9.2 M V 1 */ + pduSessionId := p_PDU_SessionId, /* cl. 9.4 M V 1 */ + procedureTransactionIdentifier := p_PTI, /* cl. 9.6 M V 1 */ + messageType := tsc_MT_NG_PDUSessionEstablishmentRequest, /* cl. 9.7 M V 1 */ + integrityProtMaxDataRate := p_IntegrityProtMaxDataRate, /* cl. 9.11.4.7 M V 2 */ + pduSessionType := p_PDU_SessionType, /* cl. 9.11.4.11 O TV 1 IEI=9 */ + sscMode := p_SSC_Mode, /* cl. 9.11.4.16 O TV 1 IEI=A */ + smCapability := p_UECap, /* cl. 9.11.4.1 O TLV 3-15 IEI=28 */ + maxNumPacketFilters := p_MaxNumPacketFilters, /* cl. 9.11.4.6 O TV 3 IEI=55 */ + alwaysOnPDUSessionReq := p_AlwaysOnPDUSessionReq, /* cl. 9.11.4.4 O TV 1 IEI=B */ + smPDU_RequestContainer := p_PDUReq, /* cl. 9.11.4.15 O TLV ? ? */ + extdProtocolConfigurationOptions := p_ExtdPCO, /* cl. 9.11.4.6 O TLV-E 4-65538 IEI=0x7B */ + ipHeaderCompressionConfig := p_IPHeaderCompConfig, /* cl. 9.11.4.24 O TLV 5-257 IEI=66 Sep20 @sic R5s201387 Baseline Moving sic@ */ + ds_TT_EthernetPortMACAddr := p_DS_TT_EthernetPortMACAddr, /* cl. 9.11.4.25 O TLV 8 IEI=6E Sep20 @sic R5s201387 Baseline Moving sic@ */ + ueDS_TT_ResidenceTime := p_UE_DS_TT_ResidenceTime, /* cl. 9.11.4.26 O TLV 10 IEI=6F Sep20 @sic R5s201387 Baseline Moving sic@ */ + portManagementInfoContainer := p_PortManagementInfoContainer, /* cl. 9.11.4.27 O TLV-E 8-65538 IEI=7C Sep20 @sic R5s201387 Baseline Moving sic@ */ + ethernetHeaderCompressConfig := p_EthernetHeaderCompConfig, /* cl. 9.11.4.28 O TLV 3 IEI=1F Sep20 @sic R5s201387 Baseline Moving sic@ */ + suggestedInterfaceId := p_SuggestedInterfaceId, /* cl. 9.11.4.10 O TLV 11 IEI=29 Sep20 @sic R5s201387 Baseline Moving sic@ */ + serviceLvlAA := p_ServiceLvlAA, /* cl. 9.11.2.10 O TLV-E 6-n IEI=72 Sep22 @sic R5s221179 Baseline Moving sic@ */ + requestedMBS := p_RequestedMBS, /* cl. 9.11.4.30 O TLV-E 8-65538 IEI=70 Sep22 @sic R5s221179 Baseline Moving sic@ */ + pduSessionPairId := p_PduSessionPairId, /* cl. 9.11.4.32 O TLV 3 IEI=34 Sep22 @sic R5s221179 Baseline Moving sic@ */ + rsn := p_RSN /* cl. 9.11.4.33 O TLV 3 IEI=35 Sep22 @sic R5s221179 Baseline Moving sic@ */ + } +} + } diff --git a/library/NG_NAS_Osmo_Types.ttcn b/library/NG_NAS_Osmo_Types.ttcn new file mode 100644 index 0000000..1e76a98 --- /dev/null +++ b/library/NG_NAS_Osmo_Types.ttcn @@ -0,0 +1,70 @@ +/* Our own NG NAS Types on top of + * deps/nas/ttcn/Lib3GPP/NG_NAS/NG_NAS_TypesDefs.ttcn, NG_NAS_MsgContainers.ttcn, + * etc. */ +module NG_NAS_Osmo_Types { + +/* (C) 2025 by sysmocom - s.f.m.c. GmbH info@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; + +import from General_Types all; + +/* 3GPP TS 24.501 9.11.3.40 Payload container type */ +const BIT4 c_PayloadContainer_N1_SM_Info := '0001'B; +const BIT4 c_PayloadContainer_SMS := '0010'B; +const BIT4 c_PayloadContainer_LPP_Msg_Container := '0011'B; +const BIT4 c_PayloadContainer_SOR_Transp_Container := '0100'B; +const BIT4 c_PayloadContainer_UE_Policy_Container := '0101'B; +const BIT4 c_PayloadContainer_UE_Pars_Upd_Transp_Container := '0110'B; +const BIT4 c_PayloadContainer_Loc_Services_Msg_Container := '0110'B; +const BIT4 c_PayloadContainer_CIoT_User_Data_Container := '0111'B; +const BIT4 c_PayloadContainer_Serv_Lvl_AA_Container := '1001'B; +const BIT4 c_PayloadContainer_Event_Notification := '1010'B; +const BIT4 c_PayloadContainer_UPP_CMI_Container := '1011'B; +const BIT4 c_PayloadContainer_SLPP_Message_Container := '1100'B; +const BIT4 c_PayloadContainer_Multiple_Payloads := '1111'B; + +/* This is a subset of the msgs in NG_NAS_DL_Message_Type. The subset is formed + * by Session Management messages, see 3GPP TS 24.501 clause 6 and clause 8.3. + * This is needed to properly decode 3GPP TS 24.501 9.11.3.39 Payload container, + * whose content changes based on 9.11.3.40 Payload container type. Trying to decode + * it through dec_NG_NAS_DL_Message_Type() may end up with unexpected union choice + * due to circumstancial match in previous field securityHeaderType. */ +type union NG_NAS_DL_SM_Message_Type { /* NAS message with direction 'network to UE' or 'both' */ + NG_PDU_SESSION_AUTHENTICATION_COMMAND pdu_Session_Authentication_Command, + NG_PDU_SESSION_AUTHENTICATION_RESULT pdu_Session_Authentication_Result, + NG_PDU_SESSION_ESTABLISHMENT_ACCEPT pdu_Session_Establishment_Accept, + NG_PDU_SESSION_ESTABLISHMENT_REJECT pdu_Session_Establishment_Reject, + NG_PDU_SESSION_MODIFICATION_COMMAND pdu_Session_Modification_Command, + NG_PDU_SESSION_MODIFICATION_REJECT pdu_Session_Modification_Reject, + NG_PDU_SESSION_RELEASE_COMMAND pdu_Session_Release_Command, + NG_PDU_SESSION_RELEASE_REJECT pdu_Session_Release_Reject, + NG_GSM_STATUS gsm_Status + } with { + variant "TAG( + pdu_Session_Authentication_Command, messageType = '11000101'B; + pdu_Session_Authentication_Result, messageType = '11000111'B; + pdu_Session_Establishment_Accept, messageType = '11000010'B; + pdu_Session_Establishment_Reject, messageType = '11000011'B; + pdu_Session_Modification_Command, messageType = '11001011'B; + pdu_Session_Modification_Reject, messageType = '11001010'B; + pdu_Session_Release_Command, messageType = '11010011'B; + pdu_Session_Release_Reject, messageType = '11010010'B; + gsm_Status, messageType = '11010110'B; + )" +}; + +} with { encode "RAW" } diff --git a/library/ngap/NGAP_EncDec.cc b/library/ngap/NGAP_EncDec.cc index c54868a..ccdfe83 100644 --- a/library/ngap/NGAP_EncDec.cc +++ b/library/ngap/NGAP_EncDec.cc @@ -1,6 +1,7 @@
#include <string.h> #include <stdarg.h> +#include "NGAP_IEs.hh" #include "NGAP_PDU_Descriptions.hh"
namespace NGAP__Types { @@ -27,4 +28,45 @@ return pdu; }
+OCTETSTRING enc__NGAP__PDUSessionResourceSetupRequestTransfer(const NGAP__IEs::PDUSessionResourceSetupRequestTransfer &p) +{ + TTCN_Buffer TTCN_buf; + TTCN_buf.clear(); + p.encode(NGAP__IEs::PDUSessionResourceSetupRequestTransfer_descr_, TTCN_buf, + TTCN_EncDec::CT_PER, PER_ALIGNED); + return OCTETSTRING(TTCN_buf.get_len(), TTCN_buf.get_data()); +} + +NGAP__IEs::PDUSessionResourceSetupRequestTransfer dec__NGAP__PDUSessionResourceSetupRequestTransfer(const OCTETSTRING &stream) +{ + NGAP__IEs::PDUSessionResourceSetupRequestTransfer ret; + TTCN_Buffer TTCN_buf; + TTCN_buf.clear(); + TTCN_buf.put_os(stream); + ret.decode(NGAP__IEs::PDUSessionResourceSetupRequestTransfer_descr_, TTCN_buf, + TTCN_EncDec::CT_PER, PER_ALIGNED); + return ret; + +} + +OCTETSTRING enc__NGAP__PDUSessionResourceSetupResponseTransfer(const NGAP__IEs::PDUSessionResourceSetupResponseTransfer &p) +{ + TTCN_Buffer TTCN_buf; + TTCN_buf.clear(); + p.encode(NGAP__IEs::PDUSessionResourceSetupResponseTransfer_descr_, TTCN_buf, + TTCN_EncDec::CT_PER, PER_ALIGNED); + return OCTETSTRING(TTCN_buf.get_len(), TTCN_buf.get_data()); +} + +NGAP__IEs::PDUSessionResourceSetupResponseTransfer dec__NGAP__PDUSessionResourceSetupResponseTransfer(const OCTETSTRING &stream) +{ + NGAP__IEs::PDUSessionResourceSetupResponseTransfer ret; + TTCN_Buffer TTCN_buf; + TTCN_buf.clear(); + TTCN_buf.put_os(stream); + ret.decode(NGAP__IEs::PDUSessionResourceSetupResponseTransfer_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 697709b..32ee82c 100644 --- a/library/ngap/NGAP_Templates.ttcn +++ b/library/ngap/NGAP_Templates.ttcn @@ -1380,11 +1380,13 @@ template (present) InitiatingMessage mw_n2_InitialContextSetupRequest_withPDUSessionList( template (present) AMF_UE_NGAP_ID p_amfUeNgapID := ?, template (present) RAN_UE_NGAP_ID p_ranUeNgapID := ?, + template (present) UEAggregateMaximumBitRate p_uEAggregateMaximumBitRate := ?, template (present) GUAMI p_gUAMI := ?, template (present) PDUSessionResourceSetupListCxtReq p_pDUSessionResourceSetupListCxtReq := ?, template (present) AllowedNSSAI p_allowedNSSAI := ?, template (present) UESecurityCapabilities p_uESecurityCapabilities := ?, - template (present) SecurityKey p_nextHopNH := ? + template (present) SecurityKey p_nextHopNH := ?, + template (present) MaskedIMEISV p_maskedIMEISV := ? ) := { procedureCode := id_InitialContextSetup, criticality := reject, @@ -1402,6 +1404,11 @@ value_ := { RAN_UE_NGAP_ID := p_ranUeNgapID } }, { + id := id_UEAggregateMaximumBitRate, + criticality := reject, + value_ := { UEAggregateMaximumBitRate := p_uEAggregateMaximumBitRate } + }, + { id := id_GUAMI, criticality := reject, value_ := { GUAMI := p_gUAMI } @@ -1425,6 +1432,11 @@ id := id_SecurityKey, criticality := reject, value_ := { SecurityKey := p_nextHopNH } + }, + { /* Optional: */ + id := id_MaskedIMEISV, + criticality := ignore, + value_ := { maskedIMEISV := p_maskedIMEISV } } } } diff --git a/library/ngap/NGAP_Types.ttcn b/library/ngap/NGAP_Types.ttcn index bddb921..dfa6586 100644 --- a/library/ngap/NGAP_Types.ttcn +++ b/library/ngap/NGAP_Types.ttcn @@ -1,7 +1,14 @@ module NGAP_Types {
+ import from NGAP_IEs language "ASN.1:2002" all; import from NGAP_PDU_Descriptions language "ASN.1:2002" all;
external function enc_NGAP_PDU(in NGAP_PDU pdu) return octetstring; external function dec_NGAP_PDU(in octetstring stream) return NGAP_PDU; + + external function enc_NGAP_PDUSessionResourceSetupRequestTransfer(NGAP_IEs.PDUSessionResourceSetupRequestTransfer p) return octetstring; + external function dec_NGAP_PDUSessionResourceSetupRequestTransfer(in octetstring pdu) return NGAP_IEs.PDUSessionResourceSetupRequestTransfer; + + external function enc_NGAP_PDUSessionResourceSetupResponseTransfer(NGAP_IEs.PDUSessionResourceSetupResponseTransfer p) return octetstring; + external function dec_NGAP_PDUSessionResourceSetupResponseTransfer(in octetstring pdu) return NGAP_IEs.PDUSessionResourceSetupResponseTransfer; }