pespin submitted this change.

View Change

Approvals: Jenkins Builder: Verified osmith: Looks good to me, but someone else must approve laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved
smf: Initial HTTP2/SBI support

* New library/TS*_Templates.ttcn files are added providing several
templates for SBI interface types available from
osmo-ttcn3-openapi-generator.git.
* Split SMF_Session_CT parts which are only used during 4G tests
(Diameter interfaces, S5/S8/S2b GTPv2C interfaces) into its own file
SMF_Session_CT_4G. There's usually no need to look at both 4G and 5G
specific code at the same time, since usually tests validate one or
the other. SMF_Session_CT is left with common stuff, like lifecycle
of component and PFCP interface.
* Add a new SMF_Session_CT_5G file containing all 5G specific logic, ie.
HTTP2 SBI interface handling.
* Add a new test in SMF_Tests which makes use of the new
SMF_Session_CT_5G logic to emulate a PDU Session request from a 5G UE.
Test and infra only validates so far until UE receives the PDU session
request after UDM/PCF validation & setup. Further work will be done in
follow-up commits.
* Adapt open5gs config to use an SCP to route all HTTP2 traffic. This
way we can emulate all nodes through a single HTTP2 server, and we
emulate the SCP forwarding the messages to the proper destination.
Hence, the NRF is disabled.

Related: SYS#7073
Change-Id: I377b748d8da6e9e53a96a85f1c730505793ecea8
---
M library/HTTP2_Functions.ttcn
A library/TS29502_Nsmf_PDUSession_Templates.ttcn
A library/TS29503_Nudm_SDM_Templates.ttcn
A library/TS29512_Npcf_SMPolicyControl_Templates.ttcn
A library/TS29518_Namf_Communication_Templates.ttcn
A library/TS29571_CommonData_Templates.ttcn
M smf/README.md
M smf/SMF_Session_CT.ttcn
A smf/SMF_Session_CT_4G.ttcn
A smf/SMF_Session_CT_5G.ttcn
M smf/SMF_Tests.ttcn
M smf/expected-results.xml
M smf/gen_links.sh
M smf/open5gs-nrf.yaml
M smf/open5gs-smf.yaml
M smf/regen_makefile.sh
M smf/testenv.cfg
17 files changed, 2,000 insertions(+), 396 deletions(-)

diff --git a/library/HTTP2_Functions.ttcn b/library/HTTP2_Functions.ttcn
index 95e5ea1..83ebdd6 100644
--- a/library/HTTP2_Functions.ttcn
+++ b/library/HTTP2_Functions.ttcn
@@ -1,10 +1,12 @@
module HTTP2_Functions {

+import from TCCConversion_Functions all; //f_strstr(), f_strstr_oct()
+
+import from Misc_Helpers all;
+
import from HTTP2_Types all;
import from HTTP2_Templates all;

-import from TCCConversion_Functions all; //f_strstr()
-
function f_HTTP2_header_list_find_header(HTTP2_header_list headers, charstring header_name)
return template (omit) charstring {
for (var integer i := 0; i < lengthof(headers); i := i + 1) {
@@ -28,5 +30,67 @@
return boundary;
}

+type record HTTP2_multipart_part {
+ HTTP2_header_list headers,
+ octetstring data
+}
+type record of HTTP2_multipart_part HTTP2_multipart_part_list;
+
+private function f_HTTP2_multipart_msg_parse_part_headers(octetstring data)
+return HTTP2_header_list {
+ var HTTP2_header_list li := {};
+ var charstring data_str := oct2char(data);
+ var charstring delim := "\r\n";
+ var ro_charstring sp := f_str_split(data_str, delim);
+ var charstring line_regexp := "([A-Za-z][A-Za-z0-9-]+):\s#()(?+)\s#()";
+ for (var integer i := 0; i < lengthof(sp); i := i + 1) {
+ if (sp[i] == "") {
+ continue;
+ }
+ var charstring header_name := regexp(sp[i], line_regexp, 0);
+ var charstring header_value := regexp(sp[i], line_regexp, 1);
+ li := li & { valueof(ts_HTTP2_header_field(header_name, header_value)) };
+ }
+ return li;
+}
+
+private function f_HTTP2_multipart_msg_parse_part(octetstring data)
+return HTTP2_multipart_part {
+ var HTTP2_multipart_part part;
+ var octetstring delim := char2oct("\r\n\r\n");
+
+ /* 0..off is headers, off+lengthof(delim)..end is the data. */
+ var integer off := f_strstr_oct(data, delim, 0);
+ var octetstring header := substr(data, 0, off);
+ off := off + lengthof(delim);
+ part := {
+ headers := f_HTTP2_multipart_msg_parse_part_headers(header),
+ data := substr(data, off, lengthof(data) - off)
+ }
+ return part;
+}
+
+function f_HTTP2_multipart_msg_parse(octetstring data, charstring boundary)
+return HTTP2_multipart_part_list {
+ var HTTP2_multipart_part_list li := {};
+ var octetstring token := char2oct("--" & boundary);
+ var ro_octetstring parts;
+
+ /* Split multiparts based on boundary: */
+ parts := f_str_oct_split(data, token);
+
+ /* Last chunk (after last boundary) should contain "--\r\n": */
+ if (lengthof(parts) < 2 or parts[lengthof(parts) - 1] != char2oct("--\r\n")) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected parsing multipart ", data, " into ", parts));
+ }
+
+ /* Parse each part and put it in the list: */
+ for (var integer i := 0; i < lengthof(parts) - 1; i := i + 1) {
+ li := li & { f_HTTP2_multipart_msg_parse_part(parts[i]) };
+ }
+ return li;
+}
+

}
diff --git a/library/TS29502_Nsmf_PDUSession_Templates.ttcn b/library/TS29502_Nsmf_PDUSession_Templates.ttcn
new file mode 100644
index 0000000..e34cd10
--- /dev/null
+++ b/library/TS29502_Nsmf_PDUSession_Templates.ttcn
@@ -0,0 +1,348 @@
+module TS29502_Nsmf_PDUSession_Templates {
+
+import from TS29502_Nsmf_PDUSession all;
+
+type TS29502_Nsmf_PDUSession.SmContextCreateData.additionalHsmfSetIdList AdditionalHsmfSetIdList;
+type TS29502_Nsmf_PDUSession.SmContextCreateData.additionalSmfSetIdList AdditionalSmfSetIdList;
+type TS29502_Nsmf_PDUSession.SmContextCreateData.nrfOauth2Required NrfOauth2Required;
+
+template (value) SmContextCreateData
+ts_SmContextCreateData(
+ template (omit) TS29502_Nsmf_PDUSession.Supi supi := omit,
+ template (omit) boolean unauthenticatedSupi := omit,
+ template (omit) boolean roamingUeInd := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Pei pei := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Gpsi gpsi := omit,
+ template (omit) TS29502_Nsmf_PDUSession.PduSessionId pduSessionId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Dnn dnn := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Dnn selectedDnn := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Snssai sNssai := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Snssai altSnssai := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Snssai hplmnSnssai := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Snssai altHplmnSnssai := omit,
+ template (value) TS29502_Nsmf_PDUSession.NfInstanceId servingNfId,
+ template (omit) TS29502_Nsmf_PDUSession.Guami guami := omit,
+ template (omit) TS29502_Nsmf_PDUSession.ServiceName serviceName := omit,
+ template (value) TS29502_Nsmf_PDUSession.PlmnIdNid servingNetwork,
+ template (omit) RequestType requestType := omit,
+ template (omit) TS29502_Nsmf_PDUSession.RefToBinaryData n1SmMsg := omit,
+ template (value) TS29502_Nsmf_PDUSession.AccessType anType,
+ template (omit) TS29502_Nsmf_PDUSession.AccessType additionalAnType := omit,
+ template (omit) TS29502_Nsmf_PDUSession.RatType ratType := omit,
+ template (omit) TS29502_Nsmf_PDUSession.PresenceState presenceInLadn := omit,
+ template (omit) boolean perLadnDnnSnssaiInd := omit,
+ template (omit) TS29502_Nsmf_PDUSession.UserLocation ueLocation := omit,
+ template (omit) TS29502_Nsmf_PDUSession.TimeZone ueTimeZone := omit,
+ template (omit) TS29502_Nsmf_PDUSession.UserLocation addUeLocation := omit,
+ template (value) TS29502_Nsmf_PDUSession.Uri smContextStatusUri,
+ template (omit) TS29502_Nsmf_PDUSession.Uri hSmfUri := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NfInstanceId hSmfId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NfSetId hSmfSetId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Uri smfUri := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NfInstanceId smfId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NfSetId smfSetId := omit,
+ template (omit) record of TS29502_Nsmf_PDUSession.Uri additionalHsmfUri := omit,
+ template (omit) record of TS29502_Nsmf_PDUSession.NfInstanceId additionalHsmfId := omit,
+ template (omit) AdditionalHsmfSetIdList additionalHsmfSetIdList := omit,
+ template (omit) record of TS29502_Nsmf_PDUSession.Uri additionalSmfUri := omit,
+ template (omit) record of TS29502_Nsmf_PDUSession.NfInstanceId additionalSmfId := omit,
+ template (omit) AdditionalSmfSetIdList additionalSmfSetIdList := omit,
+ template (omit) TS29502_Nsmf_PDUSession.PduSessionId oldPduSessionId := omit,
+ template (omit) record of TS29502_Nsmf_PDUSession.PduSessionId pduSessionsActivateList := omit,
+ template (omit) EpsPdnCnxContainer ueEpsPdnConnection := omit,
+ template (omit) HoState hoState := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NfInstanceId pcfId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NfGroupId pcfGroupId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NfSetId pcfSetId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Uri nrfUri := omit,
+ template (omit) TS29502_Nsmf_PDUSession.SupportedFeatures supportedFeatures := omit,
+ template (omit) TS29502_Nsmf_PDUSession.SupportedFeatures anchorSmfFeatures := omit,
+ template (omit) record of TS29502_Nsmf_PDUSession.SupportedFeatures additionalAnchorSmfFeatures := omit,
+ template (omit) DnnSelectionMode selMode := omit,
+ template (omit) TS29502_Nsmf_PDUSession.SmContextCreateData.backupAmfInfo backupAmfInfo := omit,
+ template (omit) TS29502_Nsmf_PDUSession.TraceData traceData := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NfGroupId udmGroupId := omit,
+ template (omit) charstring routingIndicator := omit,
+ template (omit) integer hNwPubKeyId := omit,
+ template (omit) EpsInterworkingIndication epsInterworkingInd := omit,
+ template (omit) boolean indirectForwardingFlag := omit,
+ template (omit) boolean directForwardingFlag := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NgRanTargetId targetId := omit,
+ template (omit) EpsBearerContextStatus epsBearerCtxStatus := omit,
+ template (omit) boolean cpCiotEnabled := omit,
+ template (omit) boolean cpOnlyInd := omit,
+ template (omit) boolean invokeNef := omit,
+ template (omit) boolean maRequestInd := omit,
+ template (omit) boolean maNwUpgradeInd := omit,
+ template (omit) boolean n3gPathSwitchSupportInd := omit,
+ template (omit) TS29502_Nsmf_PDUSession.RefToBinaryData n2SmInfo := omit,
+ template (omit) N2SmInfoType n2SmInfoType := omit,
+ template (omit) TS29502_Nsmf_PDUSession.RefToBinaryData n2SmInfoExt1 := omit,
+ template (omit) N2SmInfoType n2SmInfoTypeExt1 := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Uri smContextRef := omit,
+ template (omit) TS29502_Nsmf_PDUSession.PlmnIdNid smContextSmfPlmnId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NfInstanceId smContextSmfId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NfSetId smContextSmfSetId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NfServiceSetId smContextSmfServiceSetId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.SbiBindingLevel smContextSmfBinding := omit,
+ template (omit) UpCnxState upCnxState := omit,
+ template (omit) TS29502_Nsmf_PDUSession.SmallDataRateStatus smallDataRateStatus := omit,
+ template (omit) TS29502_Nsmf_PDUSession.ApnRateStatus apnRateStatus := omit,
+ template (omit) boolean extendedNasSmTimerInd := omit,
+ template (omit) boolean dlDataWaitingInd := omit,
+ template (omit) DdnFailureSubs ddnFailureSubs := omit,
+ template (omit) boolean smfTransferInd := omit,
+ template (omit) TS29502_Nsmf_PDUSession.NfInstanceId oldSmfId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Uri oldSmContextRef := omit,
+ template (omit) TS29502_Nsmf_PDUSession.WAgfInfo wAgfInfo := omit,
+ template (omit) TS29502_Nsmf_PDUSession.TngfInfo tngfInfo := omit,
+ template (omit) TS29502_Nsmf_PDUSession.TwifInfo twifInfo := omit,
+ template (omit) boolean ranUnchangedInd := omit,
+ template (omit) boolean samePcfSelectionInd := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Dnai targetDnai := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Uri nrfManagementUri := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Uri nrfDiscoveryUri := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Uri nrfAccessTokenUri := omit,
+ template (omit) NrfOauth2Required nrfOauth2Required := omit,
+ template (omit) charstring smfBindingInfo := omit,
+ template (omit) TS29502_Nsmf_PDUSession.SmContextCreateData.pvsInfo pvsInfo := omit,
+ template (omit) boolean onboardingInd := omit,
+ template (omit) TS29502_Nsmf_PDUSession.Uri oldPduSessionRef := omit,
+ template (omit) boolean smPolicyNotifyInd := omit,
+ template (omit) TS29502_Nsmf_PDUSession.PcfUeCallbackInfo pcfUeCallbackInfo := omit,
+ template (omit) TS29502_Nsmf_PDUSession.SatelliteBackhaulCategory satelliteBackhaulCat := omit,
+ template (omit) boolean upipSupported := omit,
+ template (omit) boolean disasterRoamingInd := omit,
+ template (omit) boolean anchorSmfOauth2Required := omit,
+ template (omit) boolean smContextSmfOauth2Required := omit,
+ template (omit) TS29502_Nsmf_PDUSession.GeoSatelliteId geoSatelliteId := omit,
+ template (omit) TS29502_Nsmf_PDUSession.SatelliteId servingSatelliteId := omit,
+ template (omit) boolean hrsboAllowedInd := omit,
+ template (omit) boolean estabRejectionInd := omit,
+ template (omit) EstablishmentRejectionCause estabRejectionCause := omit,
+ template (omit) boolean sliceAreaRestrictInd := omit,
+ template (omit) QosMonitoringPdSupported qosMonitoringPdSupported := omit,
+ template (omit) TS29502_Nsmf_PDUSession.SmContextCreateData.qosMonitoringPdMethods qosMonitoringPdMethods := omit,
+ template (omit) QosMonitoringCongestionSupported qosMonitoringCongestionSupported := omit,
+ template (omit) AvailBitRateMonSupported availBitRateMonSupported := omit,
+ template (omit) TS29502_Nsmf_PDUSession.UeLevelMeasurementsConfiguration ueLevelMeasConfig := omit,
+ template (omit) boolean pgwChangeInd := omit,
+ template (omit) boolean localOffloadingMgtAllowedInd := omit,
+ template (omit) boolean priorityUserInd := omit
+) := {
+ supi := supi,
+ unauthenticatedSupi := unauthenticatedSupi,
+ roamingUeInd := roamingUeInd,
+ pei := pei,
+ gpsi := gpsi,
+ pduSessionId := pduSessionId,
+ dnn := dnn,
+ selectedDnn := selectedDnn,
+ sNssai := sNssai,
+ altSnssai := altSnssai,
+ hplmnSnssai := hplmnSnssai,
+ altHplmnSnssai := altHplmnSnssai,
+ servingNfId := servingNfId,
+ guami := guami,
+ serviceName := serviceName,
+ servingNetwork := servingNetwork,
+ requestType := requestType,
+ n1SmMsg := n1SmMsg,
+ anType := anType,
+ additionalAnType := additionalAnType,
+ ratType := ratType,
+ presenceInLadn := presenceInLadn,
+ perLadnDnnSnssaiInd := perLadnDnnSnssaiInd,
+ ueLocation := ueLocation,
+ ueTimeZone := ueTimeZone,
+ addUeLocation := addUeLocation,
+ smContextStatusUri := smContextStatusUri,
+ hSmfUri := hSmfUri,
+ hSmfId := hSmfId,
+ hSmfSetId := hSmfSetId,
+ smfUri := smfUri,
+ smfId := smfId,
+ smfSetId := smfSetId,
+ additionalHsmfUri := additionalHsmfUri,
+ additionalHsmfId := additionalHsmfId,
+ additionalHsmfSetIdList := additionalHsmfSetIdList,
+ additionalSmfUri := additionalSmfUri,
+ additionalSmfId := additionalSmfId,
+ additionalSmfSetIdList := additionalSmfSetIdList,
+ oldPduSessionId := oldPduSessionId,
+ pduSessionsActivateList := pduSessionsActivateList,
+ ueEpsPdnConnection := ueEpsPdnConnection,
+ hoState := hoState,
+ pcfId := pcfId,
+ pcfGroupId := pcfGroupId,
+ pcfSetId := pcfSetId,
+ nrfUri := nrfUri,
+ supportedFeatures := supportedFeatures,
+ anchorSmfFeatures := anchorSmfFeatures,
+ additionalAnchorSmfFeatures := additionalAnchorSmfFeatures,
+ selMode := selMode,
+ backupAmfInfo := backupAmfInfo,
+ traceData := traceData,
+ udmGroupId := udmGroupId,
+ routingIndicator := routingIndicator,
+ hNwPubKeyId := hNwPubKeyId,
+ epsInterworkingInd := epsInterworkingInd,
+ indirectForwardingFlag := indirectForwardingFlag,
+ directForwardingFlag := directForwardingFlag,
+ targetId := targetId,
+ epsBearerCtxStatus := epsBearerCtxStatus,
+ cpCiotEnabled := cpCiotEnabled,
+ cpOnlyInd := cpOnlyInd,
+ invokeNef := invokeNef,
+ maRequestInd := maRequestInd,
+ maNwUpgradeInd := maNwUpgradeInd,
+ n3gPathSwitchSupportInd := n3gPathSwitchSupportInd,
+ n2SmInfo := n2SmInfo,
+ n2SmInfoType := n2SmInfoType,
+ n2SmInfoExt1 := n2SmInfoExt1,
+ n2SmInfoTypeExt1 := n2SmInfoTypeExt1,
+ smContextRef := smContextRef,
+ smContextSmfPlmnId := smContextSmfPlmnId,
+ smContextSmfId := smContextSmfId,
+ smContextSmfSetId := smContextSmfSetId,
+ smContextSmfServiceSetId := smContextSmfServiceSetId,
+ smContextSmfBinding := smContextSmfBinding,
+ upCnxState := upCnxState,
+ smallDataRateStatus := smallDataRateStatus,
+ apnRateStatus := apnRateStatus,
+ extendedNasSmTimerInd := extendedNasSmTimerInd,
+ dlDataWaitingInd := dlDataWaitingInd,
+ ddnFailureSubs := ddnFailureSubs,
+ smfTransferInd := smfTransferInd,
+ oldSmfId := oldSmfId,
+ oldSmContextRef := oldSmContextRef,
+ wAgfInfo := wAgfInfo,
+ tngfInfo := tngfInfo,
+ twifInfo := twifInfo,
+ ranUnchangedInd := ranUnchangedInd,
+ samePcfSelectionInd := samePcfSelectionInd,
+ targetDnai := targetDnai,
+ nrfManagementUri := nrfManagementUri,
+ nrfDiscoveryUri := nrfDiscoveryUri,
+ nrfAccessTokenUri := nrfAccessTokenUri,
+ nrfOauth2Required := nrfOauth2Required,
+ smfBindingInfo := smfBindingInfo,
+ pvsInfo := pvsInfo,
+ onboardingInd := onboardingInd,
+ oldPduSessionRef := oldPduSessionRef,
+ smPolicyNotifyInd := smPolicyNotifyInd,
+ pcfUeCallbackInfo := pcfUeCallbackInfo,
+ satelliteBackhaulCat := satelliteBackhaulCat,
+ upipSupported := upipSupported,
+ disasterRoamingInd := disasterRoamingInd,
+ anchorSmfOauth2Required := anchorSmfOauth2Required,
+ smContextSmfOauth2Required := smContextSmfOauth2Required,
+ geoSatelliteId := geoSatelliteId,
+ servingSatelliteId := servingSatelliteId,
+ hrsboAllowedInd := hrsboAllowedInd,
+ estabRejectionInd := estabRejectionInd,
+ estabRejectionCause := estabRejectionCause,
+ sliceAreaRestrictInd := sliceAreaRestrictInd,
+ qosMonitoringPdSupported := qosMonitoringPdSupported,
+ qosMonitoringPdMethods := qosMonitoringPdMethods,
+ qosMonitoringCongestionSupported := qosMonitoringCongestionSupported,
+ availBitRateMonSupported := availBitRateMonSupported,
+ ueLevelMeasConfig := ueLevelMeasConfig,
+ pgwChangeInd := pgwChangeInd,
+ localOffloadingMgtAllowedInd := localOffloadingMgtAllowedInd,
+ priorityUserInd := priorityUserInd
+}
+
+template (value) RefToBinaryData
+ts_RefToBinaryData(template (value) charstring contentId) := {
+ contentId := contentId
+}
+
+template (value) Snssai
+ts_Snssai(template (value) integer sst,
+ template (omit) charstring sd := omit) := {
+ sst := sst,
+ sd := sd
+}
+
+template (value) Guami
+ts_Guami(template (value) PlmnIdNid plmnId,
+ template (value) AmfId amfId) := {
+ plmnId := plmnId,
+ amfId := amfId
+}
+
+template (value) PlmnId
+ts_PlmnId(template (value) Mcc mcc,
+ template (value) Mnc mnc) := {
+ mcc := mcc,
+ mnc := mnc
+}
+
+template (value) PlmnIdNid
+ts_PlmnIdNid(template (value) Mcc mcc,
+ template (value) Mnc mnc,
+ template (omit) Nid nid := omit) := {
+ mcc := mcc,
+ mnc := mnc,
+ nid := nid
+}
+
+template (value) RatType
+ts_RatType(template (value) RatType_enum enum_val) := {
+ enum_val := enum_val
+}
+
+template (value) UserLocation
+ts_UserLocation(template (omit) EutraLocation eutraLocation := omit,
+ template (omit) NrLocation nrLocation := omit,
+ template (omit) N3gaLocation n3gaLocation := omit,
+ template (omit) UtraLocation utraLocation := omit,
+ template (omit) GeraLocation geraLocation := omit) := {
+ eutraLocation := eutraLocation,
+ nrLocation := nrLocation,
+ n3gaLocation := n3gaLocation,
+ utraLocation := utraLocation,
+ geraLocation := geraLocation
+}
+
+template (value) NrLocation
+ts_NrLocation(template (value) Tai tai,
+ template (value) Ncgi ncgi,
+ template (omit) boolean ignoreNcgi := omit,
+ template (omit) integer ageOfLocationInformation := omit,
+ template (omit) DateTime ueLocationTimestamp := omit,
+ template (omit) charstring geographicalInformation := omit,
+ template (omit) charstring geodeticInformation := omit,
+ template (omit) GlobalRanNodeId globalGnbId := omit,
+ template (omit) NtnTaiInfo ntnTaiInfo := omit) := {
+ tai := tai,
+ ncgi := ncgi,
+ ignoreNcgi := ignoreNcgi,
+ ageOfLocationInformation := ageOfLocationInformation,
+ ueLocationTimestamp := ueLocationTimestamp,
+ geographicalInformation := geographicalInformation,
+ geodeticInformation := geodeticInformation,
+ globalGnbId := globalGnbId,
+ ntnTaiInfo := ntnTaiInfo
+}
+
+template (value) Tai
+ts_Tai(template (value) PlmnId plmnId,
+ template (value) Tac tac,
+ template (omit) Nid nid := omit) := {
+ plmnId := plmnId,
+ tac := tac,
+ nid := nid
+}
+
+template (value) Ncgi
+ts_Ncgi(template (value) PlmnId plmnId,
+ template (value) NrCellId nrCellId,
+ template (omit) Nid nid := omit) := {
+ plmnId := plmnId,
+ nrCellId := nrCellId,
+ nid := nid
+}
+
+}
diff --git a/library/TS29503_Nudm_SDM_Templates.ttcn b/library/TS29503_Nudm_SDM_Templates.ttcn
new file mode 100644
index 0000000..43c85e0
--- /dev/null
+++ b/library/TS29503_Nudm_SDM_Templates.ttcn
@@ -0,0 +1,326 @@
+module TS29503_Nudm_SDM_Templates {
+
+import from TS29503_Nudm_SDM all;
+
+template (value) PduSessionType1
+ts_PduSessionType1(template (value) PduSessionType1_enum enum_val) := {
+ enum_val := enum_val
+}
+
+type TS29503_Nudm_SDM.PduSessionTypes1.allowedSessionTypes PduSessionType1List;
+template (value) PduSessionTypes1
+ts_PduSessionTypes1(template (omit) PduSessionType1 defaultSessionType := omit,
+ template (omit) PduSessionType1List allowedSessionTypes := omit) := {
+ defaultSessionType := defaultSessionType,
+ allowedSessionTypes := allowedSessionTypes
+}
+
+template (value) SscMode1
+ts_SscMode1(template (value) SscMode1_enum enum_val) := {
+ enum_val := enum_val
+}
+
+type TS29503_Nudm_SDM.SscModes1.allowedSscModes SscMode1List;
+template (value) SscModes1
+ts_SscModes1(template (value) SscMode1 defaultSscMode,
+ template (omit) SscMode1List allowedSscModes := omit) := {
+ defaultSscMode := defaultSscMode,
+ allowedSscModes := allowedSscModes
+}
+
+template (value) ArpPriorityLevel
+ts_ArpPriorityLevel(template (value) integer val) := {
+ val := val
+}
+
+template (value) PreemptionCapability
+ts_PreemptionCapability(template (value) PreemptionCapability_enum enum_val) := {
+ enum_val := enum_val
+}
+
+template (value) PreemptionVulnerability
+ts_PreemptionVulnerability(template (value) PreemptionVulnerability_enum enum_val) := {
+ enum_val := enum_val
+}
+
+template (value) Arp
+ts_Arp(template (value) ArpPriorityLevel priorityLevel,
+ template (value) PreemptionCapability preemptCap,
+ template (value) PreemptionVulnerability preemptVuln) := {
+ priorityLevel := priorityLevel,
+ preemptCap := preemptCap,
+ preemptVuln := preemptVuln
+}
+
+template (value) SubscribedDefaultQos1
+ts_SubscribedDefaultQos1(template (value) FiveQi fiveqi,
+ template (value) Arp arp,
+ template (omit) FiveQiPriorityLevel priorityLevel := omit) := {
+fiveqi := fiveqi,
+arp := arp,
+priorityLevel := priorityLevel
+}
+
+template (value) Ambr1
+ts_Ambr1(template (value) BitRate uplink,
+ template (value) BitRate downlink) := {
+ uplink := uplink,
+ downlink := downlink
+}
+
+template (value) DnnConfiguration1
+ts_DnnConfiguration1(template (value) PduSessionTypes1 pduSessionTypes,
+ template (value) SscModes1 sscModes,
+ template (omit) IwkEpsInd1 iwkEpsInd := omit,
+ template (omit) SubscribedDefaultQos1 fivegQosProfile := omit,
+ template (omit) Ambr1 sessionAmbr := omit,
+ template (omit) ThreeGppChargingCharacteristics1 threegppChargingCharacteristics := omit,
+ template (omit) DnnConfiguration1.staticIpAddress staticIpAddress := omit,
+ template (omit) UpSecurity1 upSecurity := omit,
+ template (omit) PduSessionContinuityInd1 pduSessionContinuityInd := omit,
+ template (omit) NefId1 niddNefId := omit,
+ template (omit) NiddInformation1 niddInfo := omit,
+ template (omit) boolean redundantSessionAllowed := omit,
+ template (omit) AcsInfo1 acsInfo := omit,
+ template (omit) DnnConfiguration1.ipv4FrameRouteList ipv4FrameRouteList := omit,
+ template (omit) DnnConfiguration1.ipv6FrameRouteList ipv6FrameRouteList := omit,
+ template (omit) boolean atsssAllowed := omit,
+ template (omit) boolean secondaryAuth := omit,
+ template (omit) boolean uavSecondaryAuth := omit,
+ template (omit) boolean dnAaaIpAddressAllocation := omit,
+ template (omit) IpAddress1 dnAaaAddress := omit,
+ template (omit) DnnConfiguration1.additionalDnAaaAddresses additionalDnAaaAddresses := omit,
+ template (omit) Fqdn1 dnAaaFqdn := omit,
+ template (omit) charstring iptvAccCtrlInfo := omit,
+ template (omit) IpIndex1 ipv4Index := omit,
+ template (omit) IpIndex1 ipv6Index := omit,
+ template (omit) EcsAddrConfigInfo1 ecsAddrConfigInfo := omit,
+ template (omit) DnnConfiguration1.additionalEcsAddrConfigInfos additionalEcsAddrConfigInfos := omit,
+ template (omit) SharedDataId1 sharedEcsAddrConfigInfo := omit,
+ template (omit) DnnConfiguration1.additionalSharedEcsAddrConfigInfoIds additionalSharedEcsAddrConfigInfoIds := omit,
+ template (omit) boolean easDiscoveryAuthorized := omit,
+ template (omit) boolean onboardingInd := omit,
+ template (omit) AerialUeIndication1 aerialUeInd := omit,
+ template (omit) integer subscribedMaxIpv6PrefixSize := omit,
+ template (omit) boolean hrSboAuthorized := omit,
+ template (omit) DnnConfiguration1.requiredUpfFunctionList requiredUpfFunctionList := omit,
+ template (omit) DnnConfiguration1.prefUpfFunctionList prefUpfFunctionList := omit,
+ template (omit) DnnConfiguration1.vlanTagAllowed vlanTagAllowed := omit,
+ template (omit) DnnConfiguration1.vlanTagHandlingInfo vlanTagHandlingInfo := omit,
+ template (omit) boolean localOffloadingMngtInd := omit
+) := {
+ pduSessionTypes := pduSessionTypes,
+ sscModes := sscModes,
+ iwkEpsInd := iwkEpsInd,
+ fivegQosProfile := fivegQosProfile,
+ sessionAmbr := sessionAmbr,
+ threegppChargingCharacteristics := threegppChargingCharacteristics,
+ staticIpAddress := staticIpAddress,
+ upSecurity := upSecurity,
+ pduSessionContinuityInd := pduSessionContinuityInd,
+ niddNefId := niddNefId,
+ niddInfo := niddInfo,
+ redundantSessionAllowed := redundantSessionAllowed,
+ acsInfo := acsInfo,
+ ipv4FrameRouteList := ipv4FrameRouteList,
+ ipv6FrameRouteList := ipv6FrameRouteList,
+ atsssAllowed := atsssAllowed,
+ secondaryAuth := secondaryAuth,
+ uavSecondaryAuth := uavSecondaryAuth,
+ dnAaaIpAddressAllocation := dnAaaIpAddressAllocation,
+ dnAaaAddress := dnAaaAddress,
+ additionalDnAaaAddresses := additionalDnAaaAddresses,
+ dnAaaFqdn := dnAaaFqdn,
+ iptvAccCtrlInfo := iptvAccCtrlInfo,
+ ipv4Index := ipv4Index,
+ ipv6Index := ipv6Index,
+ ecsAddrConfigInfo := ecsAddrConfigInfo,
+ additionalEcsAddrConfigInfos := additionalEcsAddrConfigInfos,
+ sharedEcsAddrConfigInfo := sharedEcsAddrConfigInfo,
+ additionalSharedEcsAddrConfigInfoIds := additionalSharedEcsAddrConfigInfoIds,
+ easDiscoveryAuthorized := easDiscoveryAuthorized,
+ onboardingInd := onboardingInd,
+ aerialUeInd := aerialUeInd,
+ subscribedMaxIpv6PrefixSize := subscribedMaxIpv6PrefixSize,
+ hrSboAuthorized := hrSboAuthorized,
+ requiredUpfFunctionList := requiredUpfFunctionList,
+ prefUpfFunctionList := prefUpfFunctionList,
+ vlanTagAllowed := vlanTagAllowed,
+ vlanTagHandlingInfo := vlanTagHandlingInfo,
+ localOffloadingMngtInd := localOffloadingMngtInd
+}
+
+
+type TS29503_Nudm_SDM.SessionManagementSubscriptionData1.dnnConfigurations DnnConfigurationMap;
+type TS29503_Nudm_SDM.SessionManagementSubscriptionData1.sharedVnGroupDataIds SharedVnGroupDataIdMap;
+type TS29503_Nudm_SDM.SessionManagementSubscriptionData1.odbExemptedDnnData OdbExemptedDnnDataMap;
+type TS29503_Nudm_SDM.SessionManagementSubscriptionData1.expectedUeBehavioursList ExpectedUeBehavioursMap;
+type TS29503_Nudm_SDM.SessionManagementSubscriptionData1.expectedUeBehaviourData ExpectedUeBehaviourDataMap;
+//type TS29503_Nudm_SDM.SessionManagementSubscriptionData1.expectedUeBehaviourData.additionalProperties ExpectedUeBehaviourData1Map;
+type TS29503_Nudm_SDM.SessionManagementSubscriptionData1.appSpecificExpectedUeBehaviourData AppSpecificExpectedUeBehaviourDataMap;
+//type TS29503_Nudm_SDM.SessionManagementSubscriptionData1.appSpecificExpectedUeBehaviourData.additionalProperties AppSpecificExpectedUeBehaviourData1Map;
+type TS29503_Nudm_SDM.SessionManagementSubscriptionData1.suggestedPacketNumDlList SuggestedPacketNumDlMap;
+
+template (value) SessionManagementSubscriptionData1
+ts_SessionManagementSubscriptionData1(template (value) Snssai1 singleNssai,
+ template (omit) DnnConfigurationMap dnnConfigurations := omit,
+ template (omit) record of GroupId1 internalGroupIds := omit,
+ template (omit) SharedVnGroupDataIdMap sharedVnGroupDataIds := omit,
+ template (omit) SharedDataId1 sharedDnnConfigurationsId := omit,
+ template (omit) OdbPacketServices1 odbPacketServices := omit,
+ template (omit) OdbExemptedDnnDataMap odbExemptedDnnData := omit,
+ template (omit) TraceData1 traceData := omit,
+ template (omit) SharedDataId1 sharedTraceDataId := omit,
+ template (omit) ExpectedUeBehavioursMap expectedUeBehavioursList := omit,
+ template (omit) ExpectedUeBehaviourDataMap expectedUeBehaviourData := omit,
+ template (omit) AppSpecificExpectedUeBehaviourDataMap appSpecificExpectedUeBehaviourData := omit,
+ template (omit) SuggestedPacketNumDlMap suggestedPacketNumDlList := omit,
+ template (omit) ThreeGppChargingCharacteristics1 threegppChargingCharacteristics := omit,
+ template (omit) NfGroupId1 chfGroupId := omit,
+ template (omit) NsacAdmissionMode1 nsacMode := omit,
+ template (omit) DurationSec1 sessInactTimer := omit,
+ template (omit) SupportedFeatures1 supportedFeatures := omit,
+ template (omit) record of SharedDataId1 additionalSharedDnnConfigurationsIds := omit,
+ template (omit) UeLevelMeasurementsConfiguration1 ueLevelMeasConfig := omit) := {
+ singleNssai := singleNssai,
+ dnnConfigurations := dnnConfigurations,
+ internalGroupIds := internalGroupIds,
+ sharedVnGroupDataIds := sharedVnGroupDataIds,
+ sharedDnnConfigurationsId := sharedDnnConfigurationsId,
+ odbPacketServices := odbPacketServices,
+ odbExemptedDnnData := odbExemptedDnnData,
+ traceData := traceData,
+ sharedTraceDataId := sharedTraceDataId,
+ expectedUeBehavioursList := expectedUeBehavioursList,
+ expectedUeBehaviourData := expectedUeBehaviourData,
+ appSpecificExpectedUeBehaviourData := appSpecificExpectedUeBehaviourData,
+ suggestedPacketNumDlList := suggestedPacketNumDlList,
+ threegppChargingCharacteristics := threegppChargingCharacteristics,
+ chfGroupId := chfGroupId,
+ nsacMode := nsacMode,
+ sessInactTimer := sessInactTimer,
+ supportedFeatures := supportedFeatures,
+ additionalSharedDnnConfigurationsIds := additionalSharedDnnConfigurationsIds,
+ ueLevelMeasConfig := ueLevelMeasConfig
+}
+
+type TS29503_Nudm_SDM.SmSubsData1.field1 SessionManagementSubscriptionData1List;
+template (value) SmSubsData1
+ts_SmSubsData1(template (value) SessionManagementSubscriptionData1List field1) := {
+ field1 := field1
+}
+
+type TS29503_Nudm_SDM.SdmSubscription1.expectedUeBehaviourThresholds ExpectedUeBehaviourThresholdsMap;
+template (present) SdmSubscription1
+tr_SdmSubscription1(template (present) NfInstanceId1 nfInstanceId := ?,
+ template boolean implicitUnsubscribe := *,
+ template DateTime1 expires := *,
+ template (present) Uri1 callbackReference := ?,
+ template ServiceName1 amfServiceName := *,
+ template (present) SdmSubscription1.monitoredResourceUris monitoredResourceUris := ?,
+ template Snssai1 singleNssai := *,
+ template Dnn1 dnn := *,
+ template charstring subscriptionId := *,
+ template PlmnId1 plmnId := *,
+ template boolean immediateReport := *,
+ template ImmediateReport1 report := *,
+ template SupportedFeatures1 supportedFeatures := *,
+ template ContextInfo1 contextInfo := *,
+ template boolean nfChangeFilter := *,
+ template boolean uniqueSubscription := *,
+ template SdmSubscription1.resetIds resetIds := *,
+ template UeContextInSmfDataSubFilter1 ueConSmfDataSubFilter := *,
+ template SdmSubscription1.adjacentPlmns adjacentPlmns := *,
+ template boolean disasterRoamingInd := *,
+ template Uri1 dataRestorationCallbackUri := *,
+ template boolean udrRestartInd := *,
+ template DateTime1 lastSynchronizationTime := *,
+ template ExpectedUeBehaviourThresholdsMap expectedUeBehaviourThresholds := *,
+ template Guami1 guami := *) := {
+ nfInstanceId := nfInstanceId,
+ implicitUnsubscribe := implicitUnsubscribe,
+ expires := expires,
+ callbackReference := callbackReference,
+ amfServiceName := amfServiceName,
+ monitoredResourceUris := monitoredResourceUris,
+ singleNssai := singleNssai,
+ dnn := dnn,
+ subscriptionId := subscriptionId,
+ plmnId := plmnId,
+ immediateReport := immediateReport,
+ report := report,
+ supportedFeatures := supportedFeatures,
+ contextInfo := contextInfo,
+ nfChangeFilter := nfChangeFilter,
+ uniqueSubscription := uniqueSubscription,
+ resetIds := resetIds,
+ ueConSmfDataSubFilter := ueConSmfDataSubFilter,
+ adjacentPlmns := adjacentPlmns,
+ disasterRoamingInd := disasterRoamingInd,
+ dataRestorationCallbackUri := dataRestorationCallbackUri,
+ udrRestartInd := udrRestartInd,
+ lastSynchronizationTime := lastSynchronizationTime,
+ expectedUeBehaviourThresholds := expectedUeBehaviourThresholds,
+ guami := guami
+}
+template (value) SdmSubscription1
+ts_SdmSubscription1(template (value) NfInstanceId1 nfInstanceId,
+ template (omit) boolean implicitUnsubscribe := omit,
+ template (omit) DateTime1 expires := omit,
+ template (value) Uri1 callbackReference,
+ template (omit) ServiceName1 amfServiceName := omit,
+ template (value) SdmSubscription1.monitoredResourceUris monitoredResourceUris,
+ template (omit) Snssai1 singleNssai := omit,
+ template (omit) Dnn1 dnn := omit,
+ template (omit) charstring subscriptionId := omit,
+ template (omit) PlmnId1 plmnId := omit,
+ template (omit) boolean immediateReport := omit,
+ template (omit) ImmediateReport1 report := omit,
+ template (omit) SupportedFeatures1 supportedFeatures := omit,
+ template (omit) ContextInfo1 contextInfo := omit,
+ template (omit) boolean nfChangeFilter := omit,
+ template (omit) boolean uniqueSubscription := omit,
+ template (omit) SdmSubscription1.resetIds resetIds := omit,
+ template (omit) UeContextInSmfDataSubFilter1 ueConSmfDataSubFilter := omit,
+ template (omit) SdmSubscription1.adjacentPlmns adjacentPlmns := omit,
+ template (omit) boolean disasterRoamingInd := omit,
+ template (omit) Uri1 dataRestorationCallbackUri := omit,
+ template (omit) boolean udrRestartInd := omit,
+ template (omit) DateTime1 lastSynchronizationTime := omit,
+ template (omit) ExpectedUeBehaviourThresholdsMap expectedUeBehaviourThresholds := omit,
+ template (omit) Guami1 guami := omit) := {
+ nfInstanceId := nfInstanceId,
+ implicitUnsubscribe := implicitUnsubscribe,
+ expires := expires,
+ callbackReference := callbackReference,
+ amfServiceName := amfServiceName,
+ monitoredResourceUris := monitoredResourceUris,
+ singleNssai := singleNssai,
+ dnn := dnn,
+ subscriptionId := subscriptionId,
+ plmnId := plmnId,
+ immediateReport := immediateReport,
+ report := report,
+ supportedFeatures := supportedFeatures,
+ contextInfo := contextInfo,
+ nfChangeFilter := nfChangeFilter,
+ uniqueSubscription := uniqueSubscription,
+ resetIds := resetIds,
+ ueConSmfDataSubFilter := ueConSmfDataSubFilter,
+ adjacentPlmns := adjacentPlmns,
+ disasterRoamingInd := disasterRoamingInd,
+ dataRestorationCallbackUri := dataRestorationCallbackUri,
+ udrRestartInd := udrRestartInd,
+ lastSynchronizationTime := lastSynchronizationTime,
+ expectedUeBehaviourThresholds := expectedUeBehaviourThresholds,
+ guami := guami
+}
+
+template (value) Snssai1
+ts_Snssai1(template (value) integer sst,
+ template (omit) charstring sd := omit) := {
+ sst := sst,
+ sd := sd
+}
+
+}
diff --git a/library/TS29512_Npcf_SMPolicyControl_Templates.ttcn b/library/TS29512_Npcf_SMPolicyControl_Templates.ttcn
new file mode 100644
index 0000000..4e12839
--- /dev/null
+++ b/library/TS29512_Npcf_SMPolicyControl_Templates.ttcn
@@ -0,0 +1,223 @@
+module TS29512_Npcf_SMPolicyControl_Templates {
+
+import from TS29512_Npcf_SMPolicyControl all;
+
+template (present) SmPolicyContextData1
+tr_SmPolicyContextData1(template AccNetChId1 accNetChId := *,
+ template AccNetChargingAddress1 chargEntityAddr := *,
+ template Gpsi1 gpsi := *,
+ template (present) Supi1 supi := ?,
+ template boolean invalidSupi := *,
+ template record of GroupId1 interGrpIds := *,
+ template (present) PduSessionId1 pduSessionId := ?,
+ template (present) PduSessionType1 pduSessionType := ?,
+ template charstring chargingcharacteristics := *,
+ template (present) Dnn1 dnn := ?,
+ template DnnSelectionMode1 dnnSelMode := *,
+ template (present) Uri1 notificationUri := ?,
+ template AccessType1 accessType := *,
+ template RatType1 ratType := *,
+ template AdditionalAccessInfo1 addAccessInfo := *,
+ template PlmnIdNid1 servingNetwork := *,
+ template UserLocation1 userLocationInfo := *,
+ template TimeZone1 ueTimeZone := *,
+ template Pei1 pei := *,
+ template Ipv4Addr1 ipv4Address := *,
+ template Ipv6Prefix1 ipv6AddressPrefix := *,
+ template charstring ipDomain := *,
+ template Ambr1 subsSessAmbr := *,
+ template charstring authProfIndex := *,
+ template SubscribedDefaultQos1 subsDefQos := *,
+ template VplmnQos1 vplmnQos := *,
+ template integer numOfPackFilter := *,
+ template boolean online := *,
+ template boolean offline := *,
+ template boolean threegppPsDataOffStatus := *,
+ template boolean refQosIndication := *,
+ template TraceData1 traceReq := *,
+ template (present) Snssai1 sliceInfo := ?,
+ template Snssai1 altSliceInfo := *,
+ template QosFlowUsage1 qosFlowUsage := *,
+ template ServingNfIdentity1 servNfId := *,
+ template SupportedFeatures1 suppFeat := *,
+ template NfInstanceId1 smfId := *,
+ template DateTime1 recoveryTime := *,
+ template MaPduIndication1 maPduInd := *,
+ template AtsssCapability1 atsssCapab := *,
+ template SmPolicyContextData1.atsssCapabs atsssCapabs := *,
+ template SmPolicyContextData1.ipv4FrameRouteList ipv4FrameRouteList := *,
+ template SmPolicyContextData1.ipv6FrameRouteList ipv6FrameRouteList := *,
+ template SatelliteBackhaulCategory1 satBackhaulCategory := *,
+ template PcfUeCallbackInfo1 pcfUeInfo := *,
+ template SmPolicyContextData1.pvsInfo pvsInfo := *,
+ template boolean onboardInd := *,
+ template SmPolicyContextData1.nwdafDatas nwdafDatas := *,
+ template UrspEnforcementInfo1 urspEnfInfo := *,
+ template SscMode1 sscMode := *,
+ template Dnn1 ueReqDnn := *,
+ template PduSessionType1 ueReqPduSessionType := *,
+ template boolean hrsboInd := *,
+ template boolean locOffloadInd := *,
+ template UePolicyTransferFailureCause1 uePolFailReport := *,
+ template boolean urspProvSuppInd := *,
+ template boolean mpxMediaInd := *,
+ template SmPolicyContextData1.trafficDescriptors trafficDescriptors := *
+) := {
+ accNetChId := accNetChId,
+ chargEntityAddr := chargEntityAddr,
+ gpsi := gpsi,
+ supi := supi,
+ invalidSupi := invalidSupi,
+ interGrpIds := interGrpIds,
+ pduSessionId := pduSessionId,
+ pduSessionType := pduSessionType,
+ chargingcharacteristics := chargingcharacteristics,
+ dnn := dnn,
+ dnnSelMode := dnnSelMode,
+ notificationUri := notificationUri,
+ accessType := accessType,
+ ratType := ratType,
+ addAccessInfo := addAccessInfo,
+ servingNetwork := servingNetwork,
+ userLocationInfo := userLocationInfo,
+ ueTimeZone := ueTimeZone,
+ pei := pei,
+ ipv4Address := ipv4Address,
+ ipv6AddressPrefix := ipv6AddressPrefix,
+ ipDomain := ipDomain,
+ subsSessAmbr := subsSessAmbr,
+ authProfIndex := authProfIndex,
+ subsDefQos := subsDefQos,
+ vplmnQos := vplmnQos,
+ numOfPackFilter := numOfPackFilter,
+ online := online,
+ offline := offline,
+ threegppPsDataOffStatus := threegppPsDataOffStatus,
+ refQosIndication := refQosIndication,
+ traceReq := traceReq,
+ sliceInfo := sliceInfo,
+ altSliceInfo := altSliceInfo,
+ qosFlowUsage := qosFlowUsage,
+ servNfId := servNfId,
+ suppFeat := suppFeat,
+ smfId := smfId,
+ recoveryTime := recoveryTime,
+ maPduInd := maPduInd,
+ atsssCapab := atsssCapab,
+ atsssCapabs := atsssCapabs,
+ ipv4FrameRouteList := ipv4FrameRouteList,
+ ipv6FrameRouteList := ipv6FrameRouteList,
+ satBackhaulCategory := satBackhaulCategory,
+ pcfUeInfo := pcfUeInfo,
+ pvsInfo := pvsInfo,
+ onboardInd := onboardInd,
+ nwdafDatas := nwdafDatas,
+ urspEnfInfo := urspEnfInfo,
+ sscMode := sscMode,
+ ueReqDnn := ueReqDnn,
+ ueReqPduSessionType := ueReqPduSessionType,
+ hrsboInd := hrsboInd,
+ locOffloadInd := locOffloadInd,
+ uePolFailReport := uePolFailReport,
+ urspProvSuppInd := urspProvSuppInd,
+ mpxMediaInd := mpxMediaInd,
+ trafficDescriptors := trafficDescriptors
+}
+
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.sessRules SessRulesMap;
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.pccRules PccRulesNullableMap;
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.qosDecs QosDecsMap;
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.chgDecs ChgDecsNullableMap;
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.traffContDecs TraffContDecsMap;
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.umDecs UmDecsNullableMap;
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.qosChars QosCharsMap;
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.qosMonDecs QosMonDecsNullableMap;
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.conds ConditionData1NullableMap;
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.policyCtrlReqTriggers PolicyCtrlReqTriggersMap;
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.praInfos PresenceInfoRm1NullableMap;
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.vplmnOffloadInfos VplmnOffloadingInfo1Map;
+type TS29512_Npcf_SMPolicyControl.SmPolicyDecision1.locOffloadInfos LocalOffloadingManagementInfo1Map;
+
+template (value) SmPolicyDecision1
+ts_SmPolicyDecision1(template (omit) SessRulesMap sessRules := omit,
+ template (omit) PccRulesNullableMap pccRules := omit,
+ template (omit) boolean pcscfRestIndication := omit,
+ template (omit) QosDecsMap qosDecs := omit,
+ template (omit) ChgDecsNullableMap chgDecs := omit,
+ template (omit) ChargingInformation1 chargingInfo := omit,
+ template (omit) NfGroupId1 chfGroupId := omit,
+ template (omit) TraffContDecsMap traffContDecs := omit,
+ template (omit) UmDecsNullableMap umDecs := omit,
+ template (omit) QosCharsMap qosChars := omit,
+ template (omit) QosMonDecsNullableMap qosMonDecs := omit,
+ template (omit) DurationSec1 reflectiveQoSTimer := omit,
+ template (omit) ConditionData1NullableMap conds := omit,
+ template (omit) DateTime1 revalidationTime := omit,
+ template (omit) boolean offline := omit,
+ template (omit) boolean online := omit,
+ template (omit) boolean offlineChOnly := omit,
+ template (omit) PolicyCtrlReqTriggersMap policyCtrlReqTriggers := omit,
+ template (omit) SmPolicyDecision1.lastReqRuleData lastReqRuleData := omit,
+ template (omit) RequestedUsageData1 lastReqUsageData := omit,
+ template (omit) PresenceInfoRm1NullableMap praInfos := omit,
+ template (omit) IpIndex1 ipv4Index := omit,
+ template (omit) IpIndex1 ipv6Index := omit,
+ template (omit) QosFlowUsage1 qosFlowUsage := omit,
+ template (omit) SmPolicyDecision1.qosMonCapRepoTypes qosMonCapRepoTypes := omit,
+ template (omit) SmPolicyAssociationReleaseCause1 relCause := omit,
+ template (omit) SupportedFeatures1 suppFeat := omit,
+ template (omit) BridgeManagementContainer1 tsnBridgeManCont := omit,
+ template (omit) PortManagementContainer1 tsnPortManContDstt := omit,
+ template (omit) SmPolicyDecision1.tsnPortManContNwtts tsnPortManContNwtts := omit,
+ template (omit) Uri1 tscNotifUri := omit,
+ template (omit) charstring tscNotifCorreId := omit,
+ template (omit) boolean redSessIndication := omit,
+ template (omit) UePolicyContainer1 uePolCont := omit,
+ template (omit) SliceUsgCtrlInfo1 sliceUsgCtrlInfo := omit,
+ template (omit) VplmnOffloadingInfo1Map vplmnOffloadInfos := omit,
+ template (omit) LocalOffloadingManagementInfo1Map locOffloadInfos := omit,
+ template (omit) VplmnDlAmbr1 vplmnDlAmbr := omit,
+ template (omit) PcSessionRecoveryStatus1 sessionRecovStatus:= omit
+) := {
+ sessRules := sessRules,
+ pccRules := pccRules,
+ pcscfRestIndication := pcscfRestIndication,
+ qosDecs := qosDecs,
+ chgDecs := chgDecs,
+ chargingInfo := chargingInfo,
+ chfGroupId := chfGroupId,
+ traffContDecs := traffContDecs,
+ umDecs := umDecs,
+ qosChars := qosChars,
+ qosMonDecs := qosMonDecs,
+ reflectiveQoSTimer := reflectiveQoSTimer,
+ conds := conds,
+ revalidationTime := revalidationTime,
+ offline := offline,
+ online := online,
+ offlineChOnly := offlineChOnly,
+ policyCtrlReqTriggers := policyCtrlReqTriggers,
+ lastReqRuleData := lastReqRuleData,
+ lastReqUsageData := lastReqUsageData,
+ praInfos := praInfos,
+ ipv4Index := ipv4Index,
+ ipv6Index := ipv6Index,
+ qosFlowUsage := qosFlowUsage,
+ qosMonCapRepoTypes := qosMonCapRepoTypes,
+ relCause := relCause,
+ suppFeat := suppFeat,
+ tsnBridgeManCont := tsnBridgeManCont,
+ tsnPortManContDstt := tsnPortManContDstt,
+ tsnPortManContNwtts := tsnPortManContNwtts,
+ tscNotifUri := tscNotifUri,
+ tscNotifCorreId := tscNotifCorreId,
+ redSessIndication := redSessIndication,
+ uePolCont := uePolCont,
+ sliceUsgCtrlInfo := sliceUsgCtrlInfo,
+ vplmnOffloadInfos := vplmnOffloadInfos,
+ locOffloadInfos := locOffloadInfos,
+ vplmnDlAmbr := vplmnDlAmbr,
+ sessionRecovStatus := sessionRecovStatus
+ }
+
+}
diff --git a/library/TS29518_Namf_Communication_Templates.ttcn b/library/TS29518_Namf_Communication_Templates.ttcn
new file mode 100644
index 0000000..acba933
--- /dev/null
+++ b/library/TS29518_Namf_Communication_Templates.ttcn
@@ -0,0 +1,65 @@
+module TS29518_Namf_Communication_Templates {
+
+import from TS29518_Namf_Communication all;
+
+
+template (present) N1N2MessageTransferReqData
+tr_N1N2MessageTransferReqData(template (omit) N1MessageContainer n1MessageContainer := omit,
+ template (omit) N2InfoContainer n2InfoContainer := omit,
+ template (omit) RefToBinaryData mtData := omit,
+ template (omit) boolean skipInd := omit,
+ template (omit) boolean lastMsgIndication := omit,
+ template (omit) PduSessionId pduSessionId := omit,
+ template (omit) CorrelationID lcsCorrelationId := omit,
+ template (omit) LMFIdentification servingLMFIdentification := omit,
+ template (omit) Ppi ppi := omit,
+ template (omit) Arp arp := omit,
+ template (omit) FiveQi fiveqi := omit,
+ template (omit) Uri n1n2FailureTxfNotifURI := omit,
+ template (omit) boolean smfReallocationInd := omit,
+ template (omit) AreaOfValidity areaOfValidity := omit,
+ template (omit) SupportedFeatures supportedFeatures := omit,
+ template (omit) Guami oldGuami := omit,
+ template (omit) boolean maAcceptedInd := omit,
+ template (omit) boolean extBufSupport := omit,
+ template (omit) AccessType targetAccess := omit,
+ template (omit) NfInstanceId nfId := omit,
+ template (omit) boolean pruInd := omit,
+ template (omit) PduSessionPriority pduSessionPrio := omit) := {
+ n1MessageContainer := n1MessageContainer,
+ n2InfoContainer := n2InfoContainer,
+ mtData := mtData,
+ skipInd := skipInd,
+ lastMsgIndication := lastMsgIndication,
+ pduSessionId := pduSessionId,
+ lcsCorrelationId := lcsCorrelationId,
+ servingLMFIdentification := servingLMFIdentification,
+ ppi := ppi,
+ arp := arp,
+ fiveqi := fiveqi,
+ n1n2FailureTxfNotifURI := n1n2FailureTxfNotifURI,
+ smfReallocationInd := smfReallocationInd,
+ areaOfValidity := areaOfValidity,
+ supportedFeatures := supportedFeatures,
+ oldGuami := oldGuami,
+ maAcceptedInd := maAcceptedInd,
+ extBufSupport := extBufSupport,
+ targetAccess := targetAccess,
+ nfId := nfId,
+ pruInd := pruInd,
+ pduSessionPrio:= pduSessionPrio
+}
+
+template (value) N1N2MessageTransferCause
+ts_N1N2MessageTransferCause(N1N2MessageTransferCause_enum enum_val) := {
+ enum_val := enum_val
+}
+
+template (value) N1N2MessageTransferRspData
+ts_N1N2MessageTransferRspData(template (value) N1N2MessageTransferCause cause,
+ template (omit) SupportedFeatures supportedFeatures := omit) := {
+ cause := cause,
+ supportedFeatures := supportedFeatures
+}
+
+}
diff --git a/library/TS29571_CommonData_Templates.ttcn b/library/TS29571_CommonData_Templates.ttcn
new file mode 100644
index 0000000..7accd38
--- /dev/null
+++ b/library/TS29571_CommonData_Templates.ttcn
@@ -0,0 +1,14 @@
+module TS29571_CommonData_Templates {
+
+import from TS29571_CommonData all;
+
+template (value) PlmnIdNid
+ts_PlmnIdNid(template (value) Mcc mcc,
+ template (value) Mnc mnc,
+ template (omit) Nid nid := omit) := {
+ mcc := mcc,
+ mnc := mnc,
+ nid := nid
+}
+
+}
diff --git a/smf/README.md b/smf/README.md
index 716c38e..0dfee3a 100644
--- a/smf/README.md
+++ b/smf/README.md
@@ -13,13 +13,18 @@
rankdir=LR;
ATS [label="ATS\nSMF_Tests.ttcn"];
SMF [label="AMF\open5gs-smfd",shape="box"];
- NRF [label="SMF\nopen5gs-nrfd"];

- ATS -> SMF [label="N11"];
- ATS -> SMF [label="N4"];
- ATS -> SMF [label="Gx"];
- ATS -> SMF [label="Gy"];
- ATS -> SMF [label="S6b"];
- SMF -> NRF [label="SBI"];
+ ATS -> SMF [dir="both",label="N4 (PFCP)"];
+ ATS -> SMF [dir="both",label="Gx (Diameter)"];
+ ATS -> SMF [dir="both",label="Gy (Diameter)"];
+ ATS -> SMF [dir="both",label="S6b (Diameter)"];
+ #4G:
+ ATS -> SMF [label="S5/S8 (GTPv2C)"];
+ ATS -> SMF [label="S2b (GTPv2C)"];
+ # 5G:
+ ATS -> SMF [label="Nsmf (SBI)"];
+ SMF -> ATS [label="Namf (SBI, over SCP)"];
+ SMF -> ATS [label="Nudm (SBI, over SCP)"];
+ SMF -> ATS [label="Npcf (SBI, over SCP)"];
}
%}
diff --git a/smf/SMF_Session_CT.ttcn b/smf/SMF_Session_CT.ttcn
index 6114167..11e9f3a 100644
--- a/smf/SMF_Session_CT.ttcn
+++ b/smf/SMF_Session_CT.ttcn
@@ -9,19 +9,12 @@
import from Misc_Helpers all;

import from GTPv1U_Emulation all;
-
import from GTPv2_Types all;
import from GTPv2_Templates all;
import from GTPv2_Emulation all;

-import from DNS_Helpers all;
-
import from DIAMETER_Types all;
import from DIAMETER_Templates all;
-import from DIAMETER_ts29_212_Templates all;
-import from DIAMETER_ts29_272_Templates all;
-import from DIAMETER_ts29_273_Templates all;
-import from DIAMETER_ts32_299_Templates all;
import from DIAMETER_Emulation all;

import from PFCP_Types all;
@@ -31,18 +24,20 @@

import from NTP_Functions all;

+import from HTTP2_Adapter all;
+import from HTTP2_Server_Emulation all;
+
import from Mutex all;

+import from SMF_Session_CT_4G all;
+import from SMF_Session_CT_5G all;
import from SMF_Tests all;

-const integer DIA_Gx := 0;
-const integer DIA_Gy := 1;
-const integer DIA_S6b := 2;
-
const OCT8 c_SEID0 := '0000000000000000'O;

/* per-session component; we typically have 1..N per testcase */
-type component SMF_Session_CT extends GTP2_ConnHdlr, GTP1U_ConnHdlr, DIAMETER_ConnHdlr, PFCP_ConnHdlr, MutexCT {
+type component SMF_Session_CT extends GTP2_ConnHdlr, GTP1U_ConnHdlr, DIAMETER_ConnHdlr,
+ PFCP_ConnHdlr, MutexCT, HTTP2_CT, HTTP2_ConnHdlr {
var SessionPars g_pars;

/* GTP-U IPv4 address remote sie */
@@ -58,6 +53,14 @@
var PDU_DIAMETER g_rx_gy;
}

+type record SessionParsGy {
+ /* In seconds. 0 => disabled, !0 => grant over CC-Time period */
+ integer validity_time,
+
+ /* Result-Code to use when sending Gy CCA, usually DIAMETER_SUCCESS */
+ DIAMETER_Resultcode cca_res_code
+};
+
type record BearerConfig {
/* EPS Bearer ID */
uint4_t ebi optional,
@@ -67,14 +70,6 @@
OCT4 teid_remote optional
};

-type record SessionParsGy {
- /* In seconds. 0 => disabled, !0 => grant over CC-Time period */
- integer validity_time,
-
- /* Result-Code to use when sending Gy CCA, usually DIAMETER_SUCCESS */
- DIAMETER_Resultcode cca_res_code
-};
-
type record FTeids {
F_TEID local,
F_TEID remote optional
@@ -160,6 +155,7 @@
/* configuration data for a given Session */
type record SessionPars {
hexstring imsi,
+ charstring imsi_str,
hexstring msisdn optional,
// serving network
GTP2C_RAT_Type rat_type,
@@ -195,6 +191,7 @@
GTP2C_PDN_Type pdn_type := GTP2C_PDN_IPv4,
template (value) PfcpParameters pfcp_pars := f_t_PfcpParams(1)) := {
imsi := imsi,
+ imsi_str := f_dec_TBCD(imsi_hex2oct(imsi)),
msisdn := msisdn,
rat_type := rat_type,
apn := apn,
@@ -223,364 +220,12 @@
runs on SMF_Session_CT {
g_pars := valueof(pars);

- if (DIAMETER_PROC[DIA_Gx].checkstate("Connected")) {
- f_diameter_expect_imsi(g_pars.imsi, idx := DIA_Gx);
- }
+ f_handler_init_4G();
+ f_handler_init_5G();

- if (DIAMETER_PROC[DIA_Gy].checkstate("Connected")) {
- f_diameter_expect_imsi(g_pars.imsi, idx := DIA_Gy);
- }
-
- if (DIAMETER_PROC[DIA_S6b].checkstate("Connected")) {
- f_diameter_expect_imsi(g_pars.imsi, idx := DIA_S6b);
- }
-
- /* allocate + register TEI{C,D} on local side */
- g_pars.teic_local := f_gtp2_allocate_teic();
- g_pars.bearer.teid_local := f_gtp1u_allocate_teid();
fn.apply();
}

-/* S6b emulation (AAA-Server) */
-private altstep as_DIA_S6b_AAR() runs on SMF_Session_CT {
- var PDU_DIAMETER rx_dia;
- [] DIAMETER[DIA_S6b].receive(tr_DIA_S6b_AAR()) -> value rx_dia {
- var template (value) PDU_DIAMETER tx_dia;
- tx_dia := f_ts_DIA_S6b_AAA(rx_dia,
- "aaa." & mp_diam_realm,
- mp_diam_realm,
- mp_diam_realm);
- DIAMETER[DIA_S6b].send(tx_dia);
- setverdict(pass);
- }
- [] DIAMETER[DIA_S6b].receive(PDU_DIAMETER:?) -> value rx_dia {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- log2str("Received unexpected DIAMETER ", rx_dia));
- }
-}
-
-/* Gx emulation (PCRF)*/
-altstep as_DIA_Gx_CCR(DCC_NONE_CC_Request_Type req_type) runs on SMF_Session_CT {
- var PDU_DIAMETER rx_dia;
- [] DIAMETER[DIA_Gx].receive(tr_DIA_Gx_CCR(req_type := req_type)) -> value rx_dia {
- var template (value) PDU_DIAMETER tx_dia := f_ts_DIA_Gx_CCA(rx_dia);
- DIAMETER[DIA_Gx].send(tx_dia);
- }
- [] DIAMETER[DIA_Gx].receive(PDU_DIAMETER:?) -> value rx_dia {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- log2str("Received unexpected DIAMETER ", rx_dia));
- }
-}
-
-/* Gy emulation (OCS) */
-private function f_tr_DIA_Gy_CCR_sess(DCC_NONE_CC_Request_Type req_type)
-runs on SMF_Session_CT return template (present) PDU_DIAMETER
-{
- var octetstring imsi := char2oct(f_dec_TBCD(imsi_hex2oct(g_pars.imsi)));
- var octetstring rat_type := int2oct(enum2int(g_pars.rat_type), 1);
- var OCT1 nsapi := int2oct(g_pars.bearer.ebi, 1);
- var OCT4 charging_char := char2oct(oct2str('0000'O)); // f_s5s8_create_session() uses hardcoded chg_car := '0000'O
- var template (present) octetstring msisdn := ?;
- var charstring smf_origin_host := "smf." & mp_diam_realm;
- var octetstring sgsn_addr := f_inet_addr(mp_pcrf_local_ip);
- var octetstring ggsn_addr := f_inet_addr(mp_smf_hostname);
-
- return DIAMETER_ts32_299_Templates.f_tr_DIA_Gy_CCR(req_type,
- imsi,
- msisdn,
- rat_type,
- nsapi,
- charging_char,
- smf_origin_host,
- mp_diam_realm,
- sgsn_addr,
- ggsn_addr);
-
-}
-
-altstep as_DIA_Gy_CCR(DCC_NONE_CC_Request_Type req_type)
-runs on SMF_Session_CT {
- [] DIAMETER[DIA_Gy].receive(f_tr_DIA_Gy_CCR_sess(req_type := req_type)) -> value g_rx_gy {
- var template (value) PDU_DIAMETER tx_dia;
- var template (omit) integer validity_time := omit;
- if (g_pars.gy.validity_time > 0) {
- validity_time := g_pars.gy.validity_time;
- }
- tx_dia := DIAMETER_ts32_299_Templates.f_ts_DIA_Gy_CCA(g_rx_gy, g_pars.gy.cca_res_code, validity_time);
- DIAMETER[DIA_Gy].send(tx_dia);
- }
- [] DIAMETER[DIA_Gy].receive(PDU_DIAMETER:?) -> value g_rx_gy {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- log2str("Received unexpected DIAMETER Gy", g_rx_gy));
- }
-}
-
-/* GTPv2C */
-private function is_s2b_iface() runs on SMF_Session_CT return boolean {
- return (g_pars.rat_type == GTP2C_RAT_WLAN or g_pars.rat_type == GTP2C_RAT_Virtual);
-}
-
-private function f_perform_ipv6_slaac() runs on SMF_Session_CT
-{
- //var UECUPS_IPv6SLAACInd ipv6slaac_ind;
- //var template (value) UECUPS_IPv6SLAAC ipv6slaac;
- //ipv6slaac := ts_UECUPS_IPv6SLAAC(
- // local_gtp_ep := ts_UECUPS_SockAddr(f_inet_addr(mp_local_hostname_u)),
- // rx_teid := oct2int(g_pars.bearer.teid_local)
- //);
- //f_gtp1u_ipv6_slaac(ipv6slaac);
- //GTP1U[0].receive(UECUPS_IPv6SLAACInd:?) -> value ipv6slaac_ind;
- //log("5GC assigned IPv6 global prefix: ", ipv6slaac_ind.ipv6_prefix, " -> ", f_inet6_ntoa(ipv6slaac_ind.ipv6_prefix & '0000000000000000'O));
-
- ///* Use the first global IPv6 address in the IPv6 prefix picked by osmo-uecups: */
- //g_ip6_addr := ipv6slaac_ind.ipv6_user_addr;
- //log("Using IPv6 global address: ", g_ip6_addr);
-}
-
-/* process one to-be-created bearer context */
-private function process_bctx_create(BearerContextGrouped bctx) runs on SMF_Session_CT
-{
- g_pars.bearer.ebi := bctx.bearerContextIEs.ePS_Bearer_ID.ePS_Bearer_ID_Value;
- /* FIXME: Cause */
-
- var integer exp_fteid_if_type;
- var BIT4 exp_fteid_instance;
- if (is_s2b_iface()) {
- exp_fteid_if_type := 33;
- exp_fteid_instance := '0100'B;
- } else {
- exp_fteid_if_type := 5;
- exp_fteid_instance := '0010'B;
- }
-
- /* find F-TEID of the P-GW U side */
- var FullyQualifiedTEID rx_fteid;
- rx_fteid := valueof(f_GTP2C_find_teid(bctx.bearerContextIEs.fullyQualifiedTEID,
- exp_fteid_if_type, exp_fteid_instance));
- g_pars.bearer.teid_remote := rx_fteid.tEID_GRE_Key;
- if (rx_fteid.v4_Flag == '1'B) {
- g_gtpu4_remote := rx_fteid.iPv4_Address;
- }
- if (rx_fteid.v6_Flag == '1'B) {
- g_gtpu6_remote := rx_fteid.iPv6_Address;
- }
-
- if (g_pars.pdn_type == GTP2C_PDN_IPv6 or
- g_pars.pdn_type == GTP2C_PDN_IPv4v6) {
- f_perform_ipv6_slaac();
- }
-}
-
-/* create a session on the SMF */
-private function f_create_session(template (value) FullyQualifiedTEID fteid_c_ie,
- template (value) FullyQualifiedTEID fteid_u_ie,
- template (omit) UserLocationInfo uli_ie := omit,
- template (omit) APCO apco := omit,
- template APCO exp_apco := *) runs on SMF_Session_CT {
- var PDU_GTPCv2 rx;
-
- /* Defaults used for s5/s8: */
- var boolean do_s6b := false;
- var template APN_Restriction apn_restriction := ?;
- /* Change behavior when on S2b: */
- if (is_s2b_iface()) {
- do_s6b := true;
- apn_restriction := omit;
- }
-
- var template (value) PDU_GTPCv2 g2c :=
- ts_GTP2C_CreateSessionReq(imsi := g_pars.imsi,
- msisdn := g_pars.msisdn,
- rat_type := enum2int(g_pars.rat_type),
- sender_fteid := fteid_c_ie,
- apn := f_enc_dns_hostname(g_pars.apn),
- pdn_type := int2bit(enum2int(g_pars.pdn_type), 3),
- teid_list := { fteid_u_ie },
- chg_car := '0000'O,
- bearer_id := g_pars.bearer.ebi,
- uli := uli_ie,
- apco := apco);
- g2c.gtpcv2_pdu.createSessionRequest.servingNetwork := ts_GTP2C_ServingNetwork('001'H, '01F'H);
-
- /////////// START MUTUAL EXCLUSION ZONE ////////////
- /* This code block cannot be executed by more than one component at a time because
- * the RANAP RAB Ass Request triggers the IUT to send PFCP Session Establishment
- * Request PDU(s), which needs 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__);
- /* Subscribe for PFCP Session Establishment Request PDU(s), which are
- * expected to have SEID set to 0, as per 3GPP TS 29.244, section 7.2.2.4.2. */
- f_PFCPEM_subscribe_seid(c_SEID0);
-
- GTP2.send(g2c);
- if (do_s6b and DIAMETER[DIA_S6b].checkstate("Connected")) {
- as_DIA_S6b_AAR();
- }
- if (DIAMETER[DIA_Gx].checkstate("Connected")) {
- as_DIA_Gx_CCR(INITIAL_REQUEST);
- }
- /* FIXME: When on S2b interface, SMF is not using the Gy interface, unknown reason. */
- if (DIAMETER[DIA_Gy].checkstate("Connected")) {
- as_DIA_Gy_CCR(INITIAL_REQUEST);
- }
-
- /* Expect PFCP Session Establishment Request. */
- as_pfcp_sess_est_req();
- /* Ask PFCPEM to route PDUs with to be indicated F-SEID to us. */
- f_PFCPEM_subscribe_seid(g_pars.pfcp_pars.local_f_seid.seid);
- /* 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__);
- /////////// END MUTUAL EXCLUSION ZONE ////////////
-
- alt {
- [] GTP2.receive(tr_GTP2C_CreateSessionResp(d_teid := g_pars.teic_local,
- cause := Request_accepted,
- apn_restriction := apn_restriction,
- exp_apco := exp_apco)) -> value rx {
- /* extract TEIDs */
- var CreateSessionResponse resp := rx.gtpcv2_pdu.createSessionResponse;
- g_pars.teic_remote := resp.fullyQualifiedTEID[0].tEID_GRE_Key;
-
- /* extract allocated address[es] */
- var PDN_Address_and_Prefix paa := resp.pDN_AddressAllocation.pDN_Address_and_Prefix;
- if (ischosen(paa.iPv4_Address)) {
- g_ip4_addr := paa.iPv4_Address;
- log("SMF assigned UE IPv4 address: ", f_inet_ntoa(g_ip4_addr));
- } else if (ischosen(paa.iPv6_Address)) {
- if (paa.iPv6_Address.prefixLength != 64) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- log2str("Got IPv6 Prefix Length ",
- paa.iPv6_Address.prefixLength, " vs exp 64"));
- }
- g_ip6_interface_id := substr(paa.iPv6_Address.iPv6_Address, 8, 8);
- log("SMF assigned IPv6 Interface Id: ", g_ip6_interface_id);
- g_ip6_addr := 'FE80000000000000'O & g_ip6_interface_id;
- log("SMF assigned IPv6 link-local Address: ", f_inet6_ntoa(g_ip6_addr));
- } else if (ischosen(paa.iPv4_IPv6)) {
- if (paa.iPv4_IPv6.prefixLength != 64) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- log2str("Got IPv6 Prefix Length ",
- paa.iPv4_IPv6.prefixLength, " vs exp 64"));
- }
- g_ip4_addr := paa.iPv4_IPv6.iPv4_Address;
- log("SMF assigned UE IPv4 address: ", f_inet_ntoa(g_ip4_addr));
- g_ip6_interface_id := substr(paa.iPv4_IPv6.iPv6_Address, 8, 8);
- log("SMF assigned IPv6 Interface Id: ", g_ip6_interface_id);
- g_ip6_addr := 'FE80000000000000'O & g_ip6_interface_id;
- log("SMF assigned IPv6 link-local Address: ", f_inet6_ntoa(g_ip6_addr));
- }
- var integer i;
- for (i := 0; i < lengthof(resp.bearerContextGrouped); i := i+1) {
- var BearerContextGrouped bctx := resp.bearerContextGrouped[i];
- select (bctx.instance) {
- case ('0000'B) { // created
- process_bctx_create(bctx);
- }
- case ('0001'B) { // removed
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- "We don't expect removed bearer contexts yet");
- }
- }
- }
- }
- [] GTP2.receive(tr_GTP2C_CreateSessionResp(d_teid:=g_pars.teic_local, cause:=?)) -> value rx {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- log2str("Unexpected CreateSessionResp(cause=",
- rx.gtpcv2_pdu.createSessionResponse.cause.causeValue, ")"));
- }
- [] GTP2.receive {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- "Unexpected GTPv2 while waiting for CreateSessionResp");
- }
- }
-
-}
-
-/* create a session on the SMF on a S5/S8 interface (from SGW )*/
-function f_s5s8_create_session() runs on SMF_Session_CT {
- var template (value) FullyQualifiedTEID fteid_c_ie, fteid_u_ie;
- var template (value) UserLocationInfo uli_ie;
-
- fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_SGW_GTPC, g_pars.teic_local, 0,
- f_inet_addr(mp_local_hostname_c), omit);
- fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_SGW_GTPU, g_pars.bearer.teid_local, 2,
- f_inet_addr(mp_local_hostname_u), omit);
-
-
- /* open5gs up to 1.2.3 won't accept it without ULI, despite not mandatory */
- var template (value) TAI tai := { '0'H, '0'H, '1'H, 'F'H, '0'H, '1'H, '0001'O };
- var template (value) ECGI ecgi := { '0'H, '0'H, '1'H, 'F'H, '0'H, '1'H, '0'H, 23 };
- uli_ie := ts_GTP2C_UserLocInfo(tai := tai, ecgi := ecgi);
-
- f_create_session(fteid_c_ie, fteid_u_ie, uli_ie);
-
-}
-
-/* create a session on the SMF on a S2b interface (from ePDG)*/
-function f_s2b_create_session(template (omit) APCO apco := omit,
- template APCO exp_apco := *) runs on SMF_Session_CT {
- var template (value) FullyQualifiedTEID fteid_c_ie, fteid_u_ie;
- var template (value) UserLocationInfo uli_ie;
-
- fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S2b_ePDG_GTPC, g_pars.teic_local, 0,
- f_inet_addr(mp_local_hostname_c), omit);
- fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S2bU_ePDG_GTPU, g_pars.bearer.teid_local, 5,
- f_inet_addr(mp_local_hostname_u), omit);
-
- var template (value) TAI tai := { '0'H, '0'H, '1'H, 'F'H, '0'H, '1'H, '0001'O };
- var template (value) ECGI ecgi := { '0'H, '0'H, '1'H, 'F'H, '0'H, '1'H, '0'H, 23 };
- uli_ie := ts_GTP2C_UserLocInfo(tai := tai, ecgi := ecgi);
-
- f_create_session(fteid_c_ie, fteid_u_ie, uli_ie := uli_ie, apco := apco, exp_apco := exp_apco);
-
-}
-
-/* delete the session from the SMF */
-function f_delete_session(template (omit) GTP2C_Cause tx_cause := omit,
- template (present) GTP2C_Cause exp_cause,
- boolean expect_pfcp := true,
- boolean expect_diameter := true) runs on SMF_Session_CT {
- var template (value) FullyQualifiedTEID fteid_c_ie
- fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_SGW_GTPC, g_pars.teic_local, 0,
- f_inet_addr(mp_local_hostname_c), omit);
- var template PDU_GTPCv2 g2c :=
- ts_GTP2C_DeleteSessionReq(d_teid := g_pars.teic_remote, cause := tx_cause,
- sender_fteid := fteid_c_ie,
- teid_list := {}, bearer_id := g_pars.bearer.ebi);
-
- GTP2.send(g2c);
-
- if (expect_pfcp) {
- as_pfcp_sess_del_req();
- }
-
- if (DIAMETER[DIA_Gx].checkstate("Connected") and expect_diameter) {
- as_DIA_Gx_CCR(TERMINATION_REQUEST);
- }
- if (DIAMETER[DIA_Gy].checkstate("Connected") and expect_diameter) {
- as_DIA_Gy_CCR(TERMINATION_REQUEST);
- }
- alt {
- [] GTP2.receive(tr_GTP2C_DeleteSessionResp(d_teid := g_pars.teic_local, cause := exp_cause)) {
- setverdict(pass);
- }
- [] GTP2.receive(tr_GTP2C_DeleteSessionResp(?, ?)) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- "Unexpected DeleteSessionResp");
- }
- [] GTP2.receive {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- "Unexpected GTPv2 while waiting for DeleteSessionResp");
- }
- }
-}
-
/*******
* PFCP
*******/
@@ -674,7 +319,7 @@
return tr_PFCP_Session_Est_Req(create_urr := create_urr);
}

-private altstep as_pfcp_sess_est_req()
+altstep as_pfcp_sess_est_req()
runs on SMF_Session_CT {
var template (present) PDU_PFCP exp_req := f_Session_tr_PFCP_Session_Est_Req();
var PDU_PFCP req;
diff --git a/smf/SMF_Session_CT_4G.ttcn b/smf/SMF_Session_CT_4G.ttcn
new file mode 100644
index 0000000..06a7e37
--- /dev/null
+++ b/smf/SMF_Session_CT_4G.ttcn
@@ -0,0 +1,399 @@
+module SMF_Session_CT_4G {
+
+import from TCCEncoding_Functions all;
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from Native_Functions all;
+import from Misc_Helpers all;
+
+import from GTPv1U_Emulation all;
+
+import from GTPv2_Types all;
+import from GTPv2_Templates all;
+import from GTPv2_Emulation all;
+
+import from DNS_Helpers all;
+
+import from DIAMETER_Types all;
+import from DIAMETER_Templates all;
+import from DIAMETER_ts29_212_Templates all;
+import from DIAMETER_ts29_272_Templates all;
+import from DIAMETER_ts29_273_Templates all;
+import from DIAMETER_ts32_299_Templates all;
+import from DIAMETER_Emulation all;
+
+import from HTTP2_Adapter all;
+import from HTTP2_Server_Emulation all;
+
+import from PFCP_Emulation all;
+import from Mutex all;
+
+import from SMF_Session_CT all;
+import from SMF_Tests all;
+
+const integer DIA_Gx := 0;
+const integer DIA_Gy := 1;
+const integer DIA_S6b := 2;
+
+function f_handler_init_4G()
+runs on SMF_Session_CT {
+
+ if (DIAMETER_PROC[DIA_Gx].checkstate("Connected")) {
+ f_diameter_expect_imsi(g_pars.imsi, idx := DIA_Gx);
+ }
+
+ if (DIAMETER_PROC[DIA_Gy].checkstate("Connected")) {
+ f_diameter_expect_imsi(g_pars.imsi, idx := DIA_Gy);
+ }
+
+ if (DIAMETER_PROC[DIA_S6b].checkstate("Connected")) {
+ f_diameter_expect_imsi(g_pars.imsi, idx := DIA_S6b);
+ }
+
+ /* allocate + register TEI{C,D} on local side */
+ g_pars.teic_local := f_gtp2_allocate_teic();
+ g_pars.bearer.teid_local := f_gtp1u_allocate_teid();
+}
+
+/* S6b emulation (AAA-Server) */
+private altstep as_DIA_S6b_AAR() runs on SMF_Session_CT {
+ var PDU_DIAMETER rx_dia;
+ [] DIAMETER[DIA_S6b].receive(tr_DIA_S6b_AAR()) -> value rx_dia {
+ var template (value) PDU_DIAMETER tx_dia;
+ tx_dia := f_ts_DIA_S6b_AAA(rx_dia,
+ "aaa." & mp_diam_realm,
+ mp_diam_realm,
+ mp_diam_realm);
+ DIAMETER[DIA_S6b].send(tx_dia);
+ setverdict(pass);
+ }
+ [] DIAMETER[DIA_S6b].receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received unexpected DIAMETER ", rx_dia));
+ }
+}
+
+/* Gx emulation (PCRF)*/
+altstep as_DIA_Gx_CCR(DCC_NONE_CC_Request_Type req_type) runs on SMF_Session_CT {
+ var PDU_DIAMETER rx_dia;
+ [] DIAMETER[DIA_Gx].receive(tr_DIA_Gx_CCR(req_type := req_type)) -> value rx_dia {
+ var template (value) PDU_DIAMETER tx_dia := f_ts_DIA_Gx_CCA(rx_dia);
+ DIAMETER[DIA_Gx].send(tx_dia);
+ }
+ [] DIAMETER[DIA_Gx].receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received unexpected DIAMETER ", rx_dia));
+ }
+}
+
+/* Gy emulation (OCS) */
+private function f_tr_DIA_Gy_CCR_sess(DCC_NONE_CC_Request_Type req_type)
+runs on SMF_Session_CT return template (present) PDU_DIAMETER
+{
+ var octetstring imsi := char2oct(f_dec_TBCD(imsi_hex2oct(g_pars.imsi)));
+ var octetstring rat_type := int2oct(enum2int(g_pars.rat_type), 1);
+ var OCT1 nsapi := int2oct(g_pars.bearer.ebi, 1);
+ var OCT4 charging_char := char2oct(oct2str('0000'O)); // f_s5s8_create_session() uses hardcoded chg_car := '0000'O
+ var template (present) octetstring msisdn := ?;
+ var charstring smf_origin_host := "smf." & mp_diam_realm;
+ var octetstring sgsn_addr := f_inet_addr(mp_pcrf_local_ip);
+ var octetstring ggsn_addr := f_inet_addr(mp_smf_hostname);
+
+ return DIAMETER_ts32_299_Templates.f_tr_DIA_Gy_CCR(req_type,
+ imsi,
+ msisdn,
+ rat_type,
+ nsapi,
+ charging_char,
+ smf_origin_host,
+ mp_diam_realm,
+ sgsn_addr,
+ ggsn_addr);
+
+}
+
+altstep as_DIA_Gy_CCR(DCC_NONE_CC_Request_Type req_type)
+runs on SMF_Session_CT {
+ [] DIAMETER[DIA_Gy].receive(f_tr_DIA_Gy_CCR_sess(req_type := req_type)) -> value g_rx_gy {
+ var template (value) PDU_DIAMETER tx_dia;
+ var template (omit) integer validity_time := omit;
+ if (g_pars.gy.validity_time > 0) {
+ validity_time := g_pars.gy.validity_time;
+ }
+ tx_dia := DIAMETER_ts32_299_Templates.f_ts_DIA_Gy_CCA(g_rx_gy, g_pars.gy.cca_res_code, validity_time);
+ DIAMETER[DIA_Gy].send(tx_dia);
+ }
+ [] DIAMETER[DIA_Gy].receive(PDU_DIAMETER:?) -> value g_rx_gy {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received unexpected DIAMETER Gy", g_rx_gy));
+ }
+}
+
+/* GTPv2C */
+private function is_s2b_iface() runs on SMF_Session_CT return boolean {
+ return (g_pars.rat_type == GTP2C_RAT_WLAN or g_pars.rat_type == GTP2C_RAT_Virtual);
+}
+
+private function f_perform_ipv6_slaac() runs on SMF_Session_CT
+{
+ //var UECUPS_IPv6SLAACInd ipv6slaac_ind;
+ //var template (value) UECUPS_IPv6SLAAC ipv6slaac;
+ //ipv6slaac := ts_UECUPS_IPv6SLAAC(
+ // local_gtp_ep := ts_UECUPS_SockAddr(f_inet_addr(mp_local_hostname_u)),
+ // rx_teid := oct2int(g_pars.bearer.teid_local)
+ //);
+ //f_gtp1u_ipv6_slaac(ipv6slaac);
+ //GTP1U[0].receive(UECUPS_IPv6SLAACInd:?) -> value ipv6slaac_ind;
+ //log("5GC assigned IPv6 global prefix: ", ipv6slaac_ind.ipv6_prefix, " -> ", f_inet6_ntoa(ipv6slaac_ind.ipv6_prefix & '0000000000000000'O));
+
+ ///* Use the first global IPv6 address in the IPv6 prefix picked by osmo-uecups: */
+ //g_ip6_addr := ipv6slaac_ind.ipv6_user_addr;
+ //log("Using IPv6 global address: ", g_ip6_addr);
+}
+
+/* process one to-be-created bearer context */
+private function process_bctx_create(BearerContextGrouped bctx) runs on SMF_Session_CT
+{
+ g_pars.bearer.ebi := bctx.bearerContextIEs.ePS_Bearer_ID.ePS_Bearer_ID_Value;
+ /* FIXME: Cause */
+
+ var integer exp_fteid_if_type;
+ var BIT4 exp_fteid_instance;
+ if (is_s2b_iface()) {
+ exp_fteid_if_type := 33;
+ exp_fteid_instance := '0100'B;
+ } else {
+ exp_fteid_if_type := 5;
+ exp_fteid_instance := '0010'B;
+ }
+
+ /* find F-TEID of the P-GW U side */
+ var FullyQualifiedTEID rx_fteid;
+ rx_fteid := valueof(f_GTP2C_find_teid(bctx.bearerContextIEs.fullyQualifiedTEID,
+ exp_fteid_if_type, exp_fteid_instance));
+ g_pars.bearer.teid_remote := rx_fteid.tEID_GRE_Key;
+ if (rx_fteid.v4_Flag == '1'B) {
+ g_gtpu4_remote := rx_fteid.iPv4_Address;
+ }
+ if (rx_fteid.v6_Flag == '1'B) {
+ g_gtpu6_remote := rx_fteid.iPv6_Address;
+ }
+
+ if (g_pars.pdn_type == GTP2C_PDN_IPv6 or
+ g_pars.pdn_type == GTP2C_PDN_IPv4v6) {
+ f_perform_ipv6_slaac();
+ }
+}
+
+/* create a session on the SMF */
+private function f_create_session(template (value) FullyQualifiedTEID fteid_c_ie,
+ template (value) FullyQualifiedTEID fteid_u_ie,
+ template (omit) UserLocationInfo uli_ie := omit,
+ template (omit) APCO apco := omit,
+ template APCO exp_apco := *) runs on SMF_Session_CT {
+ var PDU_GTPCv2 rx;
+
+ /* Defaults used for s5/s8: */
+ var boolean do_s6b := false;
+ var template APN_Restriction apn_restriction := ?;
+ /* Change behavior when on S2b: */
+ if (is_s2b_iface()) {
+ do_s6b := true;
+ apn_restriction := omit;
+ }
+
+ var template (value) PDU_GTPCv2 g2c :=
+ ts_GTP2C_CreateSessionReq(imsi := g_pars.imsi,
+ msisdn := g_pars.msisdn,
+ rat_type := enum2int(g_pars.rat_type),
+ sender_fteid := fteid_c_ie,
+ apn := f_enc_dns_hostname(g_pars.apn),
+ pdn_type := int2bit(enum2int(g_pars.pdn_type), 3),
+ teid_list := { fteid_u_ie },
+ chg_car := '0000'O,
+ bearer_id := g_pars.bearer.ebi,
+ uli := uli_ie,
+ apco := apco);
+ g2c.gtpcv2_pdu.createSessionRequest.servingNetwork := ts_GTP2C_ServingNetwork('001'H, '01F'H);
+
+ /////////// START MUTUAL EXCLUSION ZONE ////////////
+ /* This code block cannot be executed by more than one component at a time because
+ * the RANAP RAB Ass Request triggers the IUT to send PFCP Session Establishment
+ * Request PDU(s), which needs 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__);
+ /* Subscribe for PFCP Session Establishment Request PDU(s), which are
+ * expected to have SEID set to 0, as per 3GPP TS 29.244, section 7.2.2.4.2. */
+ f_PFCPEM_subscribe_seid(c_SEID0);
+
+ GTP2.send(g2c);
+ if (do_s6b and DIAMETER[DIA_S6b].checkstate("Connected")) {
+ as_DIA_S6b_AAR();
+ }
+ if (DIAMETER[DIA_Gx].checkstate("Connected")) {
+ as_DIA_Gx_CCR(INITIAL_REQUEST);
+ }
+ /* FIXME: When on S2b interface, SMF is not using the Gy interface, unknown reason. */
+ if (DIAMETER[DIA_Gy].checkstate("Connected")) {
+ as_DIA_Gy_CCR(INITIAL_REQUEST);
+ }
+
+ /* Expect PFCP Session Establishment Request. */
+ as_pfcp_sess_est_req();
+ /* Ask PFCPEM to route PDUs with to be indicated F-SEID to us. */
+ f_PFCPEM_subscribe_seid(g_pars.pfcp_pars.local_f_seid.seid);
+ /* 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__);
+ /////////// END MUTUAL EXCLUSION ZONE ////////////
+
+ alt {
+ [] GTP2.receive(tr_GTP2C_CreateSessionResp(d_teid := g_pars.teic_local,
+ cause := Request_accepted,
+ apn_restriction := apn_restriction,
+ exp_apco := exp_apco)) -> value rx {
+ /* extract TEIDs */
+ var CreateSessionResponse resp := rx.gtpcv2_pdu.createSessionResponse;
+ g_pars.teic_remote := resp.fullyQualifiedTEID[0].tEID_GRE_Key;
+
+ /* extract allocated address[es] */
+ var PDN_Address_and_Prefix paa := resp.pDN_AddressAllocation.pDN_Address_and_Prefix;
+ if (ischosen(paa.iPv4_Address)) {
+ g_ip4_addr := paa.iPv4_Address;
+ log("SMF assigned UE IPv4 address: ", f_inet_ntoa(g_ip4_addr));
+ } else if (ischosen(paa.iPv6_Address)) {
+ if (paa.iPv6_Address.prefixLength != 64) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Got IPv6 Prefix Length ",
+ paa.iPv6_Address.prefixLength, " vs exp 64"));
+ }
+ g_ip6_interface_id := substr(paa.iPv6_Address.iPv6_Address, 8, 8);
+ log("SMF assigned IPv6 Interface Id: ", g_ip6_interface_id);
+ g_ip6_addr := 'FE80000000000000'O & g_ip6_interface_id;
+ log("SMF assigned IPv6 link-local Address: ", f_inet6_ntoa(g_ip6_addr));
+ } else if (ischosen(paa.iPv4_IPv6)) {
+ if (paa.iPv4_IPv6.prefixLength != 64) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Got IPv6 Prefix Length ",
+ paa.iPv4_IPv6.prefixLength, " vs exp 64"));
+ }
+ g_ip4_addr := paa.iPv4_IPv6.iPv4_Address;
+ log("SMF assigned UE IPv4 address: ", f_inet_ntoa(g_ip4_addr));
+ g_ip6_interface_id := substr(paa.iPv4_IPv6.iPv6_Address, 8, 8);
+ log("SMF assigned IPv6 Interface Id: ", g_ip6_interface_id);
+ g_ip6_addr := 'FE80000000000000'O & g_ip6_interface_id;
+ log("SMF assigned IPv6 link-local Address: ", f_inet6_ntoa(g_ip6_addr));
+ }
+ var integer i;
+ for (i := 0; i < lengthof(resp.bearerContextGrouped); i := i+1) {
+ var BearerContextGrouped bctx := resp.bearerContextGrouped[i];
+ select (bctx.instance) {
+ case ('0000'B) { // created
+ process_bctx_create(bctx);
+ }
+ case ('0001'B) { // removed
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "We don't expect removed bearer contexts yet");
+ }
+ }
+ }
+ }
+ [] GTP2.receive(tr_GTP2C_CreateSessionResp(d_teid:=g_pars.teic_local, cause:=?)) -> value rx {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected CreateSessionResp(cause=",
+ rx.gtpcv2_pdu.createSessionResponse.cause.causeValue, ")"));
+ }
+ [] GTP2.receive {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Unexpected GTPv2 while waiting for CreateSessionResp");
+ }
+ }
+
+}
+
+/* create a session on the SMF on a S5/S8 interface (from SGW )*/
+function f_s5s8_create_session() runs on SMF_Session_CT {
+ var template (value) FullyQualifiedTEID fteid_c_ie, fteid_u_ie;
+ var template (value) UserLocationInfo uli_ie;
+
+ fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_SGW_GTPC, g_pars.teic_local, 0,
+ f_inet_addr(mp_local_hostname_c), omit);
+ fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_SGW_GTPU, g_pars.bearer.teid_local, 2,
+ f_inet_addr(mp_local_hostname_u), omit);
+
+
+ /* open5gs up to 1.2.3 won't accept it without ULI, despite not mandatory */
+ var template (value) TAI tai := { '0'H, '0'H, '1'H, 'F'H, '0'H, '1'H, '0001'O };
+ var template (value) ECGI ecgi := { '0'H, '0'H, '1'H, 'F'H, '0'H, '1'H, '0'H, 23 };
+ uli_ie := ts_GTP2C_UserLocInfo(tai := tai, ecgi := ecgi);
+
+ f_create_session(fteid_c_ie, fteid_u_ie, uli_ie);
+
+}
+
+/* create a session on the SMF on a S2b interface (from ePDG)*/
+function f_s2b_create_session(template (omit) APCO apco := omit,
+ template APCO exp_apco := *) runs on SMF_Session_CT {
+ var template (value) FullyQualifiedTEID fteid_c_ie, fteid_u_ie;
+ var template (value) UserLocationInfo uli_ie;
+
+ fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S2b_ePDG_GTPC, g_pars.teic_local, 0,
+ f_inet_addr(mp_local_hostname_c), omit);
+ fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S2bU_ePDG_GTPU, g_pars.bearer.teid_local, 5,
+ f_inet_addr(mp_local_hostname_u), omit);
+
+ var template (value) TAI tai := { '0'H, '0'H, '1'H, 'F'H, '0'H, '1'H, '0001'O };
+ var template (value) ECGI ecgi := { '0'H, '0'H, '1'H, 'F'H, '0'H, '1'H, '0'H, 23 };
+ uli_ie := ts_GTP2C_UserLocInfo(tai := tai, ecgi := ecgi);
+
+ f_create_session(fteid_c_ie, fteid_u_ie, uli_ie := uli_ie, apco := apco, exp_apco := exp_apco);
+
+}
+
+/* delete the session from the SMF */
+function f_delete_session(template (omit) GTP2C_Cause tx_cause := omit,
+ template (present) GTP2C_Cause exp_cause,
+ boolean expect_pfcp := true,
+ boolean expect_diameter := true) runs on SMF_Session_CT {
+ var template (value) FullyQualifiedTEID fteid_c_ie
+ fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_SGW_GTPC, g_pars.teic_local, 0,
+ f_inet_addr(mp_local_hostname_c), omit);
+ var template PDU_GTPCv2 g2c :=
+ ts_GTP2C_DeleteSessionReq(d_teid := g_pars.teic_remote, cause := tx_cause,
+ sender_fteid := fteid_c_ie,
+ teid_list := {}, bearer_id := g_pars.bearer.ebi);
+
+ GTP2.send(g2c);
+
+ if (expect_pfcp) {
+ as_pfcp_sess_del_req();
+ }
+
+ if (DIAMETER[DIA_Gx].checkstate("Connected") and expect_diameter) {
+ as_DIA_Gx_CCR(TERMINATION_REQUEST);
+ }
+ if (DIAMETER[DIA_Gy].checkstate("Connected") and expect_diameter) {
+ as_DIA_Gy_CCR(TERMINATION_REQUEST);
+ }
+ alt {
+ [] GTP2.receive(tr_GTP2C_DeleteSessionResp(d_teid := g_pars.teic_local, cause := exp_cause)) {
+ setverdict(pass);
+ }
+ [] GTP2.receive(tr_GTP2C_DeleteSessionResp(?, ?)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Unexpected DeleteSessionResp");
+ }
+ [] GTP2.receive {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Unexpected GTPv2 while waiting for DeleteSessionResp");
+ }
+ }
+}
+
+}
diff --git a/smf/SMF_Session_CT_5G.ttcn b/smf/SMF_Session_CT_5G.ttcn
new file mode 100644
index 0000000..71047a7
--- /dev/null
+++ b/smf/SMF_Session_CT_5G.ttcn
@@ -0,0 +1,441 @@
+module SMF_Session_CT_5G {
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from Native_Functions all;
+import from Misc_Helpers all;
+
+import from HTTP2_Types all;
+import from HTTP2_Templates all;
+import from HTTP2_Functions all;
+import from HTTP2_Adapter all;
+import from HTTP2_Server_Emulation all;
+
+import from TS29518_Namf_Communication all;
+import from TS29503_Nudm_SDM all;
+import from TS29502_Nsmf_PDUSession all;
+import from TS29512_Npcf_SMPolicyControl all;
+
+import from TS29518_Namf_Communication_Templates all;
+import from TS29503_Nudm_SDM_Templates all;
+import from TS29502_Nsmf_PDUSession_Templates all;
+import from TS29512_Npcf_SMPolicyControl_Templates all;
+
+import from PFCP_Emulation all;
+import from Mutex all;
+
+import from SMF_Session_CT all;
+import from SMF_Tests all;
+
+/* Index in SMF_Session_CT inherited HTTP2_ConnHdlr ports HTTP2_CONN[] and HTTP2_CONN_PROC[] */
+const integer HTTP2_CONN_SCP := 0;
+
+function f_handler_init_5G()
+runs on SMF_Session_CT {
+ /* Create SCP HTTP2 sever, where IUT will send all SBI requests: */
+ f_http2_server_emu_register();
+}
+
+/********************************************
+ * N11 Nsmf (SBI): Requests towards IUT SMF
+ ********************************************/
+
+function f_n11_init() runs on SMF_Session_CT {
+ f_http2_adapter_init();
+ f_http2_adapter_connect(mp_smf_hostname, mp_smf_sbi_port, mp_amf_local_ip, -1);
+
+ var template (value) HTTP2_Setting_list settings := {
+ ts_HTTP2_Setting_ENABLE_PUSH(0),
+ ts_HTTP2_Setting_INITIAL_WINDOW_SIZE(4194304),
+ ts_HTTP2_Setting_MAX_HEADER_LIST_SIZE(10485760)
+ }
+ f_http2_adapter_send(ts_HTTP2_Frame_Settings(settings := settings));
+
+ f_http2_adapter_send(ts_HTTP2_Frame_Window_Update(0, 1073741824));
+}
+
+function f_http2_header_block_encode(HTTP2_header_block hb) return octetstring
+{
+ var HTTP2_comp_context ctx := HTTP2_comp_context_init();
+ var integer rc;
+ var octetstring data := ''O;
+
+ rc := HTTP2_comp_context_encode(ctx, hb, data);
+ if (rc != 0) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("HTTP2_comp_context_encode returned ", rc));
+ }
+ HTTP2_comp_context_free(ctx);
+ return data;
+}
+
+function f_http2_encode_body_multipart_json_5gnas(octetstring json_encoded,
+ octetstring nas_ecnoded,
+ charstring boundary := "=-0EVVjxcWWFYNd1JXh1OQEg==") return octetstring
+{
+ var charstring boundary_ext := "\r\n--" & boundary & "\r\n";
+ var octetstring boundary_enc := char2oct(boundary_ext);
+
+ return boundary_enc &
+ char2oct("Content-Type: application/json\r\n\r\n") &
+ json_encoded &
+ boundary_enc &
+ char2oct("Content-Id: 5gnas-sm\r\n") &
+ char2oct("Content-Type: application/vnd.3gpp.5gnas\r\n\r\n") &
+ nas_ecnoded &
+ boundary_enc;
+}
+
+/* Nsmf_PDUSession_CreateSMContext Request/response
+ * 3GPP TS 23.502 Figure 4.3.2.2.1-1
+ * 3GPP TS 29.502 6.1.3.2 */
+function f_n11_create_session()
+runs on SMF_Session_CT {
+ var octetstring hdr_enc;
+ var template (value) HTTP2_pseudo_headers pseudo_hdr;
+ var template (value) HTTP2_header_list hdr_li;
+ var template (value) HTTP2_header_block hb;
+ var template (value) octetstring body;
+ var template (value) TS29502_Nsmf_PDUSession.PlmnId plmn_id := TS29502_Nsmf_PDUSession_Templates.ts_PlmnId("001", "001");
+ var template (value) TS29502_Nsmf_PDUSession.PlmnIdNid plmn_id_nid := TS29502_Nsmf_PDUSession_Templates.ts_PlmnIdNid(plmn_id.mcc, plmn_id.mnc);
+ var integer pduSessionId := 1;
+
+ var template (value) SmContextCreateData sm_contexts;
+ var octetstring sm_contexts_enc;
+ sm_contexts := ts_SmContextCreateData(supi := "imsi-" & g_pars.imsi_str,
+ pei := "imeisv-0790219824011594",
+ pduSessionId := pduSessionId,
+ dnn := "internet",
+ sNssai := TS29502_Nsmf_PDUSession_Templates.ts_Snssai(1),
+ servingNfId := "foobar",
+ guami := ts_Guami(plmnId := plmn_id_nid,
+ amfId := "020040"),
+ servingNetwork := plmn_id_nid,
+ n1SmMsg := TS29502_Nsmf_PDUSession_Templates.ts_RefToBinaryData("5gnas-sm"),
+ anType := ThreeGPP_ACCESS,
+ ratType := ts_RatType(NR),
+ ueLocation := ts_UserLocation(nrLocation := ts_NrLocation(tai := ts_Tai(plmn_id, "000001"),
+ ncgi := ts_Ncgi(plmn_id, "000000000"))),
+ smContextStatusUri := f_amf_callback_uri(g_pars.imsi_str, "sm-context-status", pduSessionId));
+ sm_contexts_enc := f_enc_SmContextCreateData(valueof(sm_contexts));
+
+ var charstring boundary := "=-0EVVjxcWWFYNd1JXh1OQEg=="
+ var octetstring nas_enc := '2e0101c1ffff91a1'O;
+ body := f_http2_encode_body_multipart_json_5gnas(sm_contexts_enc, nas_enc, boundary);
+
+ pseudo_hdr := ts_HTTP2_pseudo_headers("POST",
+ "http",
+ mp_smf_hostname & ":" & int2str(mp_smf_sbi_port),
+ "/nsmf-pdusession/v1/sm-contexts");
+ hdr_li := {
+ ts_HTTP2_Hdr_content_type("multipart/related; boundary=\"" & boundary & "\""),
+ ts_HTTP2_Hdr_accept("application/json,application/vnd.3gpp.ngap,application/problem+json"),
+ ts_HTTP2_Hdr_user_agent("ttcn3-amf"),
+ ts_HTTP2_Hdr_content_length(int2str(lengthof(body))),
+ ts_HTTP2_Hdr_accept_encoding("gzip")
+ };
+ hb := ts_HTTP2_header_block(pseudo_hdr, hdr_li);
+ hdr_enc := f_http2_header_block_encode(valueof(hb));
+ f_http2_adapter_send(ts_HTTP2_Frame_Header(3,
+ end_stream_flag := false,
+ end_header_flag := true,
+ header_block_fragment := hdr_enc
+ ));
+
+
+ /////////// START MUTUAL EXCLUSION ZONE ////////////
+ /* This code block cannot be executed by more than one component at a time because
+ * the RANAP RAB Ass Request triggers the IUT to send PFCP Session Establishment
+ * Request PDU(s), which needs 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__);
+ /* Subscribe for PFCP Session Establishment Request PDU(s), which are
+ * expected to have SEID set to 0, as per 3GPP TS 29.244, section 7.2.2.4.2. */
+ f_PFCPEM_subscribe_seid(c_SEID0);
+
+ f_http2_adapter_send(ts_HTTP2_Frame_Data(3,
+ end_stream_flag := true,
+ data := body));
+
+ /* Expect UDM to receive GET sm-data: */
+ as_nudm_sdm_get_sm_data();
+ /* Expect UDM to receive POST sdm-subscriptions: */
+ as_nudm_sdm_post_sdm_subscriptions();
+ /* Expect PCF to receive POST sm-policies: */
+ as_npcf_smpolicycontrol_post_sm_policies();
+
+ /* Expect PFCP Session Establishment Request. */
+ as_pfcp_sess_est_req();
+ /* Ask PFCPEM to route PDUs with to be indicated F-SEID to us. */
+ f_PFCPEM_subscribe_seid(g_pars.pfcp_pars.local_f_seid.seid);
+ /* 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__);
+ /////////// END MUTUAL EXCLUSION ZONE ////////////
+
+ as_namf_comm_post_n1n2_messages();
+ setverdict(pass);
+ f_sleep(3.0);
+}
+
+function f_n11_delete_session()
+runs on SMF_Session_CT {
+ log("f_n11_delete_session(): TODO");
+}
+
+/**************************************
+ * N11 Namf (SBI): Emulated AMF
+ **************************************/
+
+const charstring Namf_Communication_API_PREFIX := "/namf-comm/v1"
+
+function f_namf_comm_uri_imsi_prefix(charstring imsi)
+return charstring {
+ return Namf_Communication_API_PREFIX & "/ue-contexts" & "/imsi-" & imsi
+}
+
+/* 3GPP TS 29.518:
+ * 6.1.3.5 Resource: N1N2 Messages Collection */
+function f_tr_Namf_Communication_post_n1n2_messages()
+runs on SMF_Session_CT return template (present) HTTP2_Msg {
+ var template (present) HTTP2_Msg http2_msg;
+ var template (present) HTTP2_header_block hb;
+ var template (present) HTTP2_pseudo_headers pseudo_headers;
+ var template HTTP2_header_list headers := *;
+
+ pseudo_headers := tr_HTTP2_pseudo_headers(method := "POST",
+ path := f_namf_comm_uri_imsi_prefix(g_pars.imsi_str) & "/n1-n2-messages");
+ hb := tr_HTTP2_header_block(pseudo_headers, headers);
+ http2_msg := tr_HTTP2_Msg(?, ?,
+ hb := hb,
+ body := tr_HTTP2_Data_frame(data := ? /* multipart */));
+ return http2_msg;
+}
+
+/* 5.2.2.3.1 N1N2MessageTransfer */
+private altstep as_namf_comm_post_n1n2_messages()
+runs on SMF_Session_CT {
+ var HTTP2_Msg http2_rx;
+ [] HTTP2_CONN[HTTP2_CONN_SCP].receive(f_tr_Namf_Communication_post_n1n2_messages()) -> value http2_rx {
+ var N1N2MessageTransferReqData n1n2msg_req;
+ var template (value) N1N2MessageTransferRspData n1n2msg_rsp;
+ var template (value) HTTP2_Msg http2_tx;
+ var octetstring body_enc;
+
+ /* Split http2_rx.body.data into chunks since it is a multipart message: */
+ var charstring content_type_val := valueof(f_HTTP2_header_list_find_header(http2_rx.hb.headers, c_HTTP2_HDR_content_type));
+ var charstring boundary := f_HTTP2_header_content_type_multipart_val_get_boundary(content_type_val)
+ var HTTP2_multipart_part_list parts := f_HTTP2_multipart_msg_parse(http2_rx.body.data, boundary);
+ log("PESPIN: rx http2 multipart! ", parts);
+
+ /* Decode 1st part: SBI json: */
+ f_dec_N1N2MessageTransferReqData(parts[0].data, n1n2msg_req); // TODO: check returned integer.
+ log("PESPIN: N1N2MessageTransferReqData:", n1n2msg_req);
+
+ /* Tx answer: */
+ n1n2msg_rsp := ts_N1N2MessageTransferRspData(cause := ts_N1N2MessageTransferCause(N1_N2_TRANSFER_INITIATED))
+ body_enc := f_enc_N1N2MessageTransferRspData(valueof(n1n2msg_rsp));
+
+ http2_tx := ts_HTTP2_Msg_200_OK(http2_rx.conn_id,
+ http2_rx.stream_id,
+ headers := {
+ ts_HTTP2_Hdr_content_type("application/json; charset=utf-8")
+ },
+ body := ts_HTTP2_Data_frame(http2_rx.stream_id,
+ end_stream_flag := true,
+ data := body_enc));
+ HTTP2_CONN[HTTP2_CONN_SCP].send(http2_tx);
+ setverdict(pass);
+ }
+}
+
+/*************************************
+ * N10 Nudm (SBI): Emulated UDM
+ *************************************/
+
+const charstring Nudm_SDM_API_PREFIX := "/nudm-sdm/v2"
+
+function f_nudm_sdm_uri_imsi_prefix(charstring imsi)
+return charstring {
+ return Nudm_SDM_API_PREFIX & "/imsi-" & imsi
+}
+
+function f_nudm_sdm_uri_imsi_subscr_prefix(charstring imsi, charstring opcode, integer pduSessionId)
+return charstring {
+ return f_nudm_sdm_uri_imsi_prefix(imsi) & "/" & opcode & "/" & int2str(pduSessionId);
+}
+
+/* 3GPP TS 29.503:
+ * 5.2.2.2.5 Session Management Subscription Data Retrieval
+ * 6.1.3.8 Resource: SessionManagementSubscriptionData (Document) */
+function f_tr_Nudm_SDM_get_sm_data()
+runs on SMF_Session_CT return template (present) HTTP2_Msg {
+ var template (present) HTTP2_Msg http2_msg;
+ var template (present) HTTP2_header_block hb;
+ var template (present) HTTP2_pseudo_headers pseudo_headers;
+ var template HTTP2_header_list headers := *;
+
+ pseudo_headers := tr_HTTP2_pseudo_headers(method := "GET",
+ path := pattern Nudm_SDM_API_PREFIX & "/imsi-" & g_pars.imsi_str & "/sm-data*");
+ hb := tr_HTTP2_header_block(pseudo_headers, headers);
+ http2_msg := tr_HTTP2_Msg(?, ?, hb := hb, body := omit);
+ return http2_msg;
+}
+
+/* 3GPP TS 29.503 5.2.2.2.5 Session Management Subscription Data Retrieval */
+private altstep as_nudm_sdm_get_sm_data()
+runs on SMF_Session_CT {
+ var HTTP2_Msg http2_rx;
+ [] HTTP2_CONN[HTTP2_CONN_SCP].receive(f_tr_Nudm_SDM_get_sm_data()) -> value http2_rx {
+ var template (value) SessionManagementSubscriptionData1 sm_sub_data;
+ var template (value) DnnConfiguration1 dnn_cfg;
+ var octetstring body_enc;
+ var template (value) HTTP2_Msg http2_tx;
+
+ dnn_cfg := ts_DnnConfiguration1(pduSessionTypes := ts_PduSessionTypes1(defaultSessionType := ts_PduSessionType1(IPV4),
+ allowedSessionTypes := { ts_PduSessionType1(IPV4) }),
+ sscModes := ts_SscModes1(defaultSscMode := ts_SscMode1(SSC_MODE_1),
+ allowedSscModes := { ts_SscMode1(SSC_MODE_1),
+ ts_SscMode1(SSC_MODE_2),
+ ts_SscMode1(SSC_MODE_3)}),
+ fivegQosProfile := ts_SubscribedDefaultQos1(fiveqi := 9,
+ arp := ts_Arp(priorityLevel := ts_ArpPriorityLevel(8),
+ preemptCap := ts_PreemptionCapability(NOT_PREEMPT),
+ preemptVuln := ts_PreemptionVulnerability(NOT_PREEMPTABLE)),
+ priorityLevel := 8),
+ sessionAmbr := ts_Ambr1(uplink := "1000 Kbps",
+ downlink := "1000 Kbps")
+ );
+
+ sm_sub_data := ts_SessionManagementSubscriptionData1(
+ singleNssai := TS29503_Nudm_SDM_Templates.ts_Snssai1(1),
+ dnnConfigurations := {{"internet", dnn_cfg}}
+ );
+ body_enc := f_enc_SmSubsData1(valueof(ts_SmSubsData1({sm_sub_data})));
+
+ http2_tx := ts_HTTP2_Msg_200_OK(http2_rx.conn_id,
+ http2_rx.stream_id,
+ headers := {
+ ts_HTTP2_Hdr_content_type("application/json; charset=utf-8")
+ },
+ body := ts_HTTP2_Data_frame(http2_rx.stream_id,
+ end_stream_flag := true,
+ data := body_enc));
+ HTTP2_CONN[HTTP2_CONN_SCP].send(http2_tx);
+ setverdict(pass);
+ }
+}
+
+
+/* 3GPP TS 29.503:
+ * 6.1.3.3 Resource: SdmSubscriptions (Collection)*/
+function f_tr_Nudm_SDM_post_sdm_subscriptions()
+runs on SMF_Session_CT return template (present) HTTP2_Msg {
+ var template (present) HTTP2_Msg http2_msg;
+ var template (present) HTTP2_header_block hb;
+ var template (present) HTTP2_pseudo_headers pseudo_headers;
+ var template HTTP2_header_list headers := *;
+
+ pseudo_headers := tr_HTTP2_pseudo_headers(method := "POST",
+ path := f_nudm_sdm_uri_imsi_prefix(g_pars.imsi_str) & "/sdm-subscriptions");
+ hb := tr_HTTP2_header_block(pseudo_headers, headers);
+ http2_msg := tr_HTTP2_Msg(?, ?,
+ hb := hb,
+ body := tr_HTTP2_Data_frame(data := decmatch tr_SdmSubscription1));
+ return http2_msg;
+}
+
+/* 3GPP TS 29.503 5.2.2.3.2 Subscription to notifications of data change */
+private altstep as_nudm_sdm_post_sdm_subscriptions()
+runs on SMF_Session_CT {
+ var HTTP2_Msg http2_rx;
+ [] HTTP2_CONN[HTTP2_CONN_SCP].receive(f_tr_Nudm_SDM_post_sdm_subscriptions()) -> value http2_rx {
+ var SdmSubscription1 sdm_subscription;
+ var template (value) HTTP2_Msg http2_tx;
+ var octetstring body_enc;
+
+ f_dec_SdmSubscription1(http2_rx.body.data, sdm_subscription); // TODO: check returned integer.
+
+ /* Add subscriptionId to received object and transmit it back: */
+ sdm_subscription.subscriptionId := "1";
+ body_enc := f_enc_SdmSubscription1(sdm_subscription);
+
+ http2_tx := ts_HTTP2_Msg_201_Created(http2_rx.conn_id,
+ http2_rx.stream_id,
+ headers := {
+ ts_HTTP2_Hdr_content_type("application/json; charset=utf-8"),
+ ts_HTTP2_Hdr_location(f_scp_uri_prefix() & f_nudm_sdm_uri_imsi_subscr_prefix(g_pars.imsi_str, "sdm-subscriptions", 1))
+ },
+ body := ts_HTTP2_Data_frame(http2_rx.stream_id,
+ end_stream_flag := true,
+ data := body_enc));
+ HTTP2_CONN[HTTP2_CONN_SCP].send(http2_tx);
+ setverdict(pass);
+ }
+}
+
+/*************************************
+ * N8 NPcf (SBI): Emulated PCF
+ *************************************/
+
+const charstring Npcf_SMPolicyControl_API_PREFIX := "/npcf-smpolicycontrol/v1"
+
+function f_npcf_smpolicycontrol_uri_imsi_prefix(charstring imsi)
+return charstring {
+ return Npcf_SMPolicyControl_API_PREFIX & "/imsi-" & imsi
+}
+
+/* 3GPP TS 29.512:
+ * 5.3.2 Resource: SM Policies */
+function f_tr_Npcf_SMPolicyControl_post_sm_policies()
+runs on SMF_Session_CT return template (present) HTTP2_Msg {
+ var template (present) HTTP2_Msg http2_msg;
+ var template (present) HTTP2_header_block hb;
+ var template (present) HTTP2_pseudo_headers pseudo_headers;
+ var template HTTP2_header_list headers := *;
+
+ pseudo_headers := tr_HTTP2_pseudo_headers(method := "POST",
+ path := Npcf_SMPolicyControl_API_PREFIX & "/sm-policies");
+ hb := tr_HTTP2_header_block(pseudo_headers, headers);
+ http2_msg := tr_HTTP2_Msg(?, ?,
+ hb := hb,
+ body := tr_HTTP2_Data_frame(data := decmatch tr_SmPolicyContextData1));
+ return http2_msg;
+}
+
+/* 3GPP TS 29.512 4.2.2.2 SM Policy Association establishment */
+private altstep as_npcf_smpolicycontrol_post_sm_policies()
+runs on SMF_Session_CT {
+ var HTTP2_Msg http2_rx;
+ [] HTTP2_CONN[HTTP2_CONN_SCP].receive(f_tr_Npcf_SMPolicyControl_post_sm_policies()) -> value http2_rx {
+ var SmPolicyContextData1 smpol_ctx_data;
+ var template (value) SmPolicyDecision1 smpol_decision;
+ var template (value) HTTP2_Msg http2_tx;
+ var octetstring body_enc;
+ var integer sessRuleId := 1;
+
+ f_dec_SmPolicyContextData1(http2_rx.body.data, smpol_ctx_data); // TODO: check returned integer.
+
+ smpol_decision := ts_SmPolicyDecision1();
+ body_enc := f_enc_SmPolicyDecision1(valueof(smpol_decision));
+
+ http2_tx := ts_HTTP2_Msg_201_Created(http2_rx.conn_id,
+ http2_rx.stream_id,
+ headers := {
+ ts_HTTP2_Hdr_content_type("application/json; charset=utf-8"),
+ ts_HTTP2_Hdr_location(f_scp_uri_prefix() & Npcf_SMPolicyControl_API_PREFIX & "/sm-policies/imsi-" & g_pars.imsi_str & "-" & int2str(sessRuleId))
+ },
+ body := ts_HTTP2_Data_frame(http2_rx.stream_id,
+ end_stream_flag := true,
+ data := body_enc));
+ HTTP2_CONN[HTTP2_CONN_SCP].send(http2_tx);
+ setverdict(pass);
+ }
+}
+
+}
diff --git a/smf/SMF_Tests.ttcn b/smf/SMF_Tests.ttcn
index b452bd9..2becc57 100644
--- a/smf/SMF_Tests.ttcn
+++ b/smf/SMF_Tests.ttcn
@@ -28,11 +28,19 @@
import from PFCP_Templates all;
import from PFCP_CodecPort all;

+import from HTTP2_Types all;
+import from HTTP2_Templates all;
+import from HTTP2_Adapter all;
+import from HTTP2_Server_Emulation all;
+
import from Mutex all;
import from SMF_Session_CT all;
+import from SMF_Session_CT_4G all;
+import from SMF_Session_CT_5G all;

modulepar {
charstring mp_smf_hostname := "127.0.0.4";
+ integer mp_smf_sbi_port := 7777;
charstring mp_local_hostname_c := "127.0.0.1";
charstring mp_local_hostname_u := "127.0.0.1";

@@ -50,10 +58,17 @@
/* IP address at which we listen for PFCP to emulate a UPF in ttcn3 */
charstring mp_pfcp_ip_local := "127.0.0.7";
charstring mp_pfcp_upf_node_id := "\07osmocom\03org";
+
+
+ /* IP address at which we listen for HTTP2/SBI to emulate a AMF in ttcn3 */
+ charstring mp_amf_local_ip := "127.0.0.4";
+ charstring mp_scp_local_ip := "127.0.1.10";
+ integer mp_scp_local_port := 7777;
}

+
/* main component, we typically have one per testcase */
-type component SMF_Test_CT extends GTP2_ConnHdlr, PFCP_ConnHdlr {
+type component SMF_Test_CT extends GTP2_ConnHdlr, PFCP_ConnHdlr, HTTP2_CT {
var GTPv2_Emulation_CT vc_GTP2;
port GTP2EM_PT TEIC0;
var GTPv1U_Emulation_CT vc_GTP1U;
@@ -77,6 +92,9 @@
var MutexDispCT vc_mutex_disp;
var boolean g_pfcp_answer_heartbeat_req := true;

+ /* emulated SCP */
+ var HTTP2_Server_Emulation_CT vc_HTTP2_SRV_SCP;
+
/* global test case guard timer (actual timeout value is set in f_init()) */
timer T_guard;
}
@@ -223,6 +241,18 @@

}

+private function f_init_http2_srv(charstring id) runs on SMF_Test_CT {
+ id := id & "-PFCP";
+
+ var Http2ServerEmulationCfg http2_srv_cfg := {
+ http2_bind_ip := mp_scp_local_ip,
+ http2_bind_port := mp_scp_local_port
+ };
+
+ vc_HTTP2_SRV_SCP := HTTP2_Server_Emulation_CT.create(id) alive;
+ vc_HTTP2_SRV_SCP.start(HTTP2_Server_Emulation.main(http2_srv_cfg));
+}
+
private function f_init(float guard_timeout := 60.0) runs on SMF_Test_CT {
T_guard.start(guard_timeout);
activate(as_Tguard());
@@ -232,6 +262,7 @@
f_init_gtp1u();

f_init_pfcp(id);
+ f_init_http2_srv(id);

if (mp_pcrf_local_ip != "") {
f_init_diameter(testcasename());
@@ -260,6 +291,11 @@
connect(vc_conn:PFCP_PROC, vc_PFCP:CLIENT_PROC);
f_MutexDisp_connect(vc_mutex_disp, vc_conn);

+ if (isbound(vc_HTTP2_SRV_SCP)) {
+ connect(vc_conn:HTTP2_CONN[HTTP2_CONN_SCP], vc_HTTP2_SRV_SCP:CONN);
+ connect(vc_conn:HTTP2_CONN_PROC[HTTP2_CONN_SCP], vc_HTTP2_SRV_SCP:CONN_PROC);
+ }
+
if (isbound(vc_Gx)) {
connect(vc_conn:DIAMETER_PROC[DIA_Gx], vc_Gx:DIAMETER_PROC);
connect(vc_conn:DIAMETER[DIA_Gx], vc_Gx:DIAMETER_CLIENT);
@@ -279,6 +315,16 @@
return vc_conn;
}

+function f_scp_uri_prefix() return charstring
+{
+ return "http://" & mp_scp_local_ip & ":" & int2str(mp_scp_local_port);
+}
+function f_amf_callback_uri(charstring imsi, charstring opcode, integer pduSessionId) return charstring
+{
+ return f_scp_uri_prefix() &
+ "/namf-callback/v1/imsi-" & imsi & "/" & opcode & "/" & int2str(pduSessionId);
+}
+
/* send echo request; expect response */
testcase TC_tx_echo() runs on SMF_Test_CT {
timer T := 5.0;
@@ -452,6 +498,21 @@
vc_conn.done;
}

+private function f_TC_n11_createSession_deleteSession() runs on SMF_Session_CT {
+ f_n11_init();
+ f_n11_create_session();
+ f_n11_delete_session();
+ setverdict(pass);
+}
+testcase TC_n11_createSession_deleteSession() runs on SMF_Test_CT {
+ var SMF_Session_CT vc_conn;
+ var SessionPars pars := valueof(t_SessionPars('001010123456789'H,
+ rat_type := GTP2C_RAT_NR));
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_n11_createSession_deleteSession), pars);
+ vc_conn.done;
+}
+
control {
execute( TC_tx_echo() );
execute( TC_createSession_deleteSession() );
@@ -460,6 +521,8 @@
execute( TC_gy_ccr_update_rejected() );
execute( TC_s2b_createSession_v4_noapco() );
execute( TC_s2b_createSession_v4_apco() );
+
+ execute( TC_n11_createSession_deleteSession() );
}


diff --git a/smf/expected-results.xml b/smf/expected-results.xml
index eba5484..a167103 100644
--- a/smf/expected-results.xml
+++ b/smf/expected-results.xml
@@ -7,4 +7,5 @@
<testcase classname='SMF_Tests' name='TC_gy_ccr_update_rejected' time='MASKED'/>
<testcase classname='SMF_Tests' name='TC_s2b_createSession_v4_noapco' time='MASKED'/>
<testcase classname='SMF_Tests' name='TC_s2b_createSession_v4_apco' time='MASKED'/>
+ <testcase classname='SMF_Tests' name='TC_n11_createSession_deleteSession' time='MASKED'/>
</testsuite>
diff --git a/smf/gen_links.sh b/smf/gen_links.sh
index f8a3166..d1b3394 100755
--- a/smf/gen_links.sh
+++ b/smf/gen_links.sh
@@ -58,6 +58,18 @@
FILES="DIAMETER_EncDec.cc"
gen_links $DIR $FILES

+DIR=$BASEDIR/titan.ProtocolModules.HTTP2/src
+FILES="HTTP2_EncDec.cc HTTP2_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.JSON_v07_2006/src
+FILES="JSON_Generic_Null_Def.asn JSON_Generic.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/osmo-ttcn3-openapi-generator/openapi-specs/3GPP_5GC_Rel19/ttcn3
+FILES="TS29571_CommonData.ttcn TS29502_Nsmf_PDUSession.ttcn TS29503_Nudm_SDM.ttcn TS29512_Npcf_SMPolicyControl.ttcn TS29518_Namf_Communication.ttcn "
+gen_links $DIR $FILES
+
DIR=../library
FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPCP_Types.ttcn IPCP_Templates.ttcn PAP_Types.ttcn "
FILES+="GTPv1C_CodecPort.ttcn GTPv1C_CodecPort_CtrlFunct.ttcn GTPv1C_CodecPort_CtrlFunctDef.cc GTPv1C_Templates.ttcn Osmocom_Gb_Types.ttcn "
@@ -70,6 +82,8 @@
FILES+="SCTP_Templates.ttcn "
FILES+="NTP_Functions.ttcn PFCP_Templates.ttcn PFCP_CodecPort.ttcn PFCP_CodecPort_CtrlFunct.ttcn PFCP_CodecPort_CtrlFunctDef.cc PFCP_Emulation.ttcn "
FILES+="Mutex.ttcn "
+FILES+="HTTP2_CodecPort.ttcn HTTP2_CodecPort_CtrlFunct.ttcn HTTP2_CodecPort_CtrlFunctDef.cc HTTP2_Templates.ttcn HTTP2_Functions.ttcn HTTP2_Adapter.ttcn HTTP2_Server_Emulation.ttcn "
+FILES+="TS29503_Nudm_SDM_Templates.ttcn TS29502_Nsmf_PDUSession_Templates.ttcn TS29512_Npcf_SMPolicyControl_Templates.ttcn TS29518_Namf_Communication_Templates.ttcn"
gen_links $DIR $FILES

gen_links_finish
diff --git a/smf/open5gs-nrf.yaml b/smf/open5gs-nrf.yaml
index 0979be0..57f5b45 100644
--- a/smf/open5gs-nrf.yaml
+++ b/smf/open5gs-nrf.yaml
@@ -3,7 +3,7 @@
db_uri: mongodb://localhost/open5gs

logger:
- level: info
+ level: debug

global:
max:
diff --git a/smf/open5gs-smf.yaml b/smf/open5gs-smf.yaml
index 34aabc3..f37de82 100644
--- a/smf/open5gs-smf.yaml
+++ b/smf/open5gs-smf.yaml
@@ -1,7 +1,7 @@
# See https://github.com/open5gs/open5gs/blob/main/configs/open5gs/smf.yaml.in

logger:
- level: info
+ level: debug

global:
max:
@@ -25,8 +25,8 @@
- address: 127.0.0.4
port: 7777
client:
- nrf:
- - uri: http://127.0.0.10:7777
+ #nrf:
+ # - uri: http://127.0.0.10:7777
scp:
- uri: http://127.0.1.10:7777
pfcp:
diff --git a/smf/regen_makefile.sh b/smf/regen_makefile.sh
index a2cb4bc..ad9ebd0 100755
--- a/smf/regen_makefile.sh
+++ b/smf/regen_makefile.sh
@@ -2,7 +2,7 @@

NAME=SMF_Tests

-FILES="
+FILES=" *.asn
*.ttcn
*.ttcnpp
BSSGP_EncDec.cc
@@ -13,6 +13,8 @@
GTPv1C_CodecPort_CtrlFunctDef.cc
GTPv1U_CodecPort_CtrlFunctDef.cc
GTPv2_CodecPort_CtrlFunctDef.cc
+ HTTP2_EncDec.cc
+ HTTP2_CodecPort_CtrlFunctDef.cc
ICMP_EncDec.cc
ICMPv6_EncDec.cc
IPL4asp_PT.cc
diff --git a/smf/testenv.cfg b/smf/testenv.cfg
index b6cbb10..837073a 100644
--- a/smf/testenv.cfg
+++ b/smf/testenv.cfg
@@ -2,12 +2,6 @@
program=SMF_Tests
config=SMF_Tests.cfg

-[nrf]
-program=open5gs-nrfd -c open5gs-nrf.yaml
-make=open5gs
-package=open5gs-nrf
-copy=open5gs-nrf.yaml
-
[smf]
program=open5gs-smfd -c open5gs-smf.yaml
make=open5gs

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

Gerrit-MessageType: merged
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I377b748d8da6e9e53a96a85f1c730505793ecea8
Gerrit-Change-Number: 43651
Gerrit-PatchSet: 5
Gerrit-Owner: pespin <pespin@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge@osmocom.org>
Gerrit-Reviewer: osmith <osmith@sysmocom.de>
Gerrit-Reviewer: pespin <pespin@sysmocom.de>
Gerrit-CC: fixeria <axilirator@gmail.com>
Gerrit-CC: fixeria <vyanitskiy@sysmocom.de>