diff --git a/internal/context/context.go b/internal/context/context.go index 3dcea3f..3b03713 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -28,6 +28,11 @@ type NRFContext struct { NrfCert *x509.Certificate NfRegistNum int nfRegistNumLock sync.RWMutex + ScpUri string + ScpIp string + ScpPortInt int + ScpHasRegister bool + ScpInfoLock sync.RWMutex } const ( @@ -48,6 +53,7 @@ func InitNrfContext() error { config.Info.Version, config.Info.Description) configuration := config.Configuration + nrfContext.ModifyScpIpInfo(false, "", "", -1) // Initiation for SCP info nrfContext.NrfNfProfile.NfInstanceId = uuid.New().String() nrfContext.NrfNfProfile.NfType = models.NfType_NRF nrfContext.NrfNfProfile.NfStatus = models.NfStatus_REGISTERED @@ -226,3 +232,12 @@ func (ctx *NRFContext) DelNfRegister() { defer ctx.nfRegistNumLock.Unlock() ctx.NfRegistNum -= 1 } + +func (ctx *NRFContext) ModifyScpIpInfo(hasRegister bool, uri string, ip string, port int) { + ctx.ScpInfoLock.Lock() + defer ctx.ScpInfoLock.Unlock() + ctx.ScpHasRegister = hasRegister + ctx.ScpUri = uri + ctx.ScpIp = ip + ctx.ScpPortInt = port +} diff --git a/internal/sbi/processor/nf_discovery.go b/internal/sbi/processor/nf_discovery.go index 2524077..ec53036 100644 --- a/internal/sbi/processor/nf_discovery.go +++ b/internal/sbi/processor/nf_discovery.go @@ -50,6 +50,7 @@ func validateQueryParameters(queryParameters url.Values) bool { "BSF": true, "CHF": true, "NWDAF": true, + "SCP": true, } var tgt, req string if queryParameters["target-nf-type"] != nil { @@ -173,6 +174,67 @@ func (p *Processor) NFDiscoveryProcedure(c *gin.Context, queryParameters url.Val } validityPeriod := 100 + // Indirect communication implementation + nrfSelf := nrf_context.GetSelf() + scpEnable := nrfSelf.ScpHasRegister + if scpEnable { + supportNFPairForIndirectCommunication := false + // Only the following NF pairs support indirect communication + nfPairs := map[string][]string{ + "AMF": {"AUSF", "SMF"}, // AMF consumes AUSF, SMF (via SCP) + "AUSF": {"UDM", "AMF"}, // AUSF consumes UDM, AMF + "UDM": {"UDR", "AUSF"}, // UDM consumes UDR, AUSF + "UDR": {"UDM", "NEF"}, // UDR consumes UDM, NEF + "SMF": {"AMF"}, // SMF consumes AMF + "NEF": {"UDR"}, // NEF consumes UDR + } + sourceNF := "" + targetNF := "" + if values, exists := queryParameters["requester-nf-type"]; exists && len(values) > 0 { + sourceNF = values[0] + } + if values, exists := queryParameters["target-nf-type"]; exists && len(values) > 0 { + targetNF = values[0] + } + + if validTargets, exists := nfPairs[sourceNF]; exists { + for _, validTarget := range validTargets { + if validTarget == targetNF { + supportNFPairForIndirectCommunication = true + } + } + } + if supportNFPairForIndirectCommunication { + logger.DiscLog.Infof( + "Discovery with indirect communication, the message will pass to SCP: [%v]", + nrfSelf.ScpUri, + ) + if len(nfProfilesStruct) > 0 { + for i := range nfProfilesStruct { + nfProfilesStruct[i].Ipv4Addresses[0] = nrfSelf.ScpUri + + if nfProfilesStruct[i].NfServices != nil { + for j := range *nfProfilesStruct[i].NfServices { + nfService := &(*nfProfilesStruct[i].NfServices)[j] + + if nfService.IpEndPoints != nil { + for k := range *nfService.IpEndPoints { + ipEndPoint := &(*nfService.IpEndPoints)[k] + ipEndPoint.Ipv4Address = nrfSelf.ScpIp + ipEndPoint.Port = int32(nrfSelf.ScpPortInt) + } + } + // for UDM search + if nfService.ApiPrefix != "" { + nfService.ApiPrefix = nrfSelf.ScpUri + } + } + } + } + } + } + } + // Build SearchResult model searchResult := &models.SearchResult{ ValidityPeriod: int32(validityPeriod), diff --git a/internal/sbi/processor/nf_management.go b/internal/sbi/processor/nf_management.go index 29692b8..4ee2be1 100644 --- a/internal/sbi/processor/nf_management.go +++ b/internal/sbi/processor/nf_management.go @@ -320,6 +320,10 @@ func (p *Processor) NFDeregisterProcedure(nfInstanceID string) *models.ProblemDe logger.NfmLog.Warningf("Can not delete NFCertPem file: %v: %v", nfCertPath, removeErr) } } + // Set SCP to unable + if nfInstanceType == models.NfType_SCP { + nrf_context.GetSelf().ModifyScpIpInfo(false, "", "", -1) + } // Minus NF Register Conter p.Context().DelNfRegister() logger.NfmLog.Infof("NfDeregister Success: %v [%v]", nfInstanceType, nfInstanceID) @@ -469,6 +473,22 @@ func (p *Processor) NFRegisterProcedure( } } + // Set scp uri for support indirect communication + // TODO: Support multiple SCP situation (This version only support for a single SCP) + if nfProfile.NfType == models.NfType_SCP && len(nfProfile.Ipv4Addresses) > 0 { + if len(nfProfile.Ipv4Addresses[0]) > 0 { + nrfSelf := nrf_context.GetSelf() + ScpIp := nfProfile.Ipv4Addresses[0] + ScpUri := "http://" + ScpIp + ":8000" // default port + nrfSelf.ModifyScpIpInfo(true, ScpUri, ScpIp, 8000) + logger.NfmLog.Infof("Update ScpUri: %v", ScpUri) + } else { + logger.NfmLog.Warnln("SCP registration request received but missing IP address.") + } + } else { + logger.NfmLog.Warnln("SCP registration request received but missing IP address.") + } + c.Writer.Header().Add("Location", locationHeaderValue) c.JSON(http.StatusOK, putData) return @@ -489,6 +509,23 @@ func (p *Processor) NFRegisterProcedure( return } } + + // Set SCP uri for support indirect communication + // TODO: Support multiple SCP situation (This version only support for a single SCP) + if nfProfile.NfType == models.NfType_SCP && len(nfProfile.Ipv4Addresses) > 0 { + if len(nfProfile.Ipv4Addresses[0]) > 0 { + nrfSelf := nrf_context.GetSelf() + ScpIp := nfProfile.Ipv4Addresses[0] + ScpUri := "http://" + ScpIp + ":8000" // default port + nrfSelf.ModifyScpIpInfo(true, ScpUri, ScpIp, 8000) + logger.NfmLog.Infof("Receive SCP register request, ScpUri: %v", ScpUri) + } else { + logger.NfmLog.Warnln("SCP registration request received but missing IP address.") + } + } else { + logger.NfmLog.Warnln("SCP registration request received but missing IP address.") + } + c.Writer.Header().Add("Location", locationHeaderValue) if factory.NrfConfig.GetOAuth() {