Free5GC源码研究(9) - PCF研究(下)

news/2024/11/14 22:27:29/文章来源:https://www.cnblogs.com/zrq96/p/18528432

前文再续书接上一回,继续研究Free5GC中所实现的PCF的另外两组服务:SMPolicy和PolicyAuthorization

SMPolicy

PCF中与SMF的交互,对session的控制有着很重的的分量,甚至连TS23.503中对与Policy Control的定义都是指PCF指示SMF去控制QoS流的过程。

Policy control: The process whereby the PCF indicates to the SMF how to control the QoS Flow. Policy control includes QoS control and/or gating control.

因为PCF的SMPolicy深度涉及了SMF的管理,因此想要研究SMPolicy就得先了解SMF相关的一些重要概念

  • QoS Flow 首先是上面提及的QoS流,全称Quality of Service Flow,是一种服务质量得到保证的传输数据流,这里的服务质量包括但不咸鱼传输速率和稳定性。每个QoS流都会由自己的ID(QFI),而一个QoS流的本质就是所有包含同一个QFI的数据包,它们在传输的时候会根据QFI得到不同的对待。QoS Flow的创建、维护、删除等由SMF负责。Free5GC团队写了一篇博客介绍它们对于QoS的理解。
  • PDU Session 全称Packet Data Unit Session,是用户设备与数据网络之间的一种逻辑连接,用于承载QoS流。一个PDU Session可以承载多个QoS流,且会有一个由SMF创建的默认QoS流。
  • PCC rule 全称Policy and Charging Control rule,标准文档中的原文是"A set of information enabling the detection of a service data flow and providing parameters for policy control and/or charging control and/or other control or support information"。简单来说就是用来对数据流进行分类处理和收费的判断规则。
  • Policy Control Request trigger 其实就是SMF应该主动发起与PCF交互的条件

了解了这些前置概念,大概就能读懂下面这张关于NBNpcf_SMPolicyControl的表格了
img

虽然标准文档里没有说明要提供GET服务,但Free5GC团队还是贴心的实现了一个根据smPolicyId找到相应的UeSmPolicyData的函数:

// https://github.com/free5gc/pcf/blob/v1.2.5/internal/sbi/processor/smpolicy.go#L546
func (p *Processor) HandleGetSmPolicyContextRequest(c *gin.Context, smPolicyId string) {ue := p.Context().PCFUeFindByPolicyId(smPolicyId)smPolicyData := ue.SmPolicyData[smPolicyId]  // ue.SmPolicyData里都是UeSmPolicyData类型response := &models.SmPolicyControl{Policy:  smPolicyData.PolicyDecision,Context: smPolicyData.PolicyContext,}c.JSON(http.StatusOK, response)
}

删除一个smPolicy的操作不仅要删除UDR喝context里的smPolicy数据,还需要删除掉与之关联的appSessionratingGroup。这个appSession在前文说过,是“PCF用来管理和追踪第三方应用程序对网络资源请求的机制”,所以删除一个用户设备的smPolicy,就会连带删除掉相应的第三方应用提供的服务;而ratingGroup则是用来对smPolicy所对应的QoS流计费的机制。

// https://github.com/free5gc/pcf/blob/v1.2.5/internal/sbi/processor/smpolicy.go#L487
func (p *Processor) HandleDeleteSmPolicyContextRequest(c *gin.Context, smPolicyId string) {ue := p.Context().PCFUeFindByPolicyId(smPolicyId)pcfSelf := p.Context()smPolicy := ue.SmPolicyData[smPolicyId]// Unsubscrice UDRp.Consumer().RemoveInfluenceDataSubscription(ue, smPolicy.SubscriptionID)delete(ue.SmPolicyData, smPolicyId)// Release related App SessionterminationInfo := models.TerminationInfo{TermCause: models.TerminationCause_PDU_SESSION_TERMINATION,}for appSessionID := range smPolicy.AppSessions {if val, exist := pcfSelf.AppSessionPool.Load(appSessionID); exist {appSession := val.(*pcf_context.AppSessionData)p.SendAppSessionTermination(appSession, terminationInfo)pcfSelf.AppSessionPool.Delete(appSessionID)}}for _, ratingGroup := range ue.RatingGroupData[smPolicyId] {pcfSelf.RatingGroupIdGenerator.FreeID(int64(ratingGroup))filterCharging := bson.M{"ratingGroup": ratingGroup,}mongoapi.RestfulAPIDeleteMany(chargingDataColl, filterCharging)}delete(ue.RatingGroupData, smPolicyId)c.JSON(http.StatusNoContent, nil)
}

相比于GET和DELETE的简单逻辑,CREATE和UPDATE的逻辑要复杂许多,free5gc用了几百行代码来实现其操作。因为Npcf_SMPolicyControl_Create操作不仅仅只是为一个用户和网络间的PDU session创建一个policy assoication,还需要做很多policy决策指示SMF怎么去控制这个PDU session(这好像是PCF最优决策存在感的操作)。

SmPolicyContextData, SmPolicyDecision
// https://github.com/free5gc/openapi/blob/v1.0.8/models/model_sm_policy_context_data.go
type SmPolicyContextData struct {AccNetChId              *AccNetChId            `json:"accNetChId,omitempty" yaml:"accNetChId" bson:"accNetChId" mapstructure:"AccNetChId"`ChargEntityAddr         *AccNetChargingAddress `json:"chargEntityAddr,omitempty" yaml:"chargEntityAddr" bson:"chargEntityAddr" mapstructure:"ChargEntityAddr"`Gpsi                    string                 `json:"gpsi,omitempty" yaml:"gpsi" bson:"gpsi" mapstructure:"Gpsi"`Supi                    string                 `json:"supi" yaml:"supi" bson:"supi" mapstructure:"Supi"`InterGrpIds             []string               `json:"interGrpIds,omitempty" yaml:"interGrpIds" bson:"interGrpIds" mapstructure:"InterGrpIds"`PduSessionId            int32                  `json:"pduSessionId" yaml:"pduSessionId" bson:"pduSessionId" mapstructure:"PduSessionId"`PduSessionType          PduSessionType         `json:"pduSessionType" yaml:"pduSessionType" bson:"pduSessionType" mapstructure:"PduSessionType"`Chargingcharacteristics string                 `json:"chargingcharacteristics,omitempty" yaml:"chargingcharacteristics" bson:"chargingcharacteristics" mapstructure:"Chargingcharacteristics"`Dnn                     string                 `json:"dnn" yaml:"dnn" bson:"dnn" mapstructure:"Dnn"`NotificationUri         string                 `json:"notificationUri" yaml:"notificationUri" bson:"notificationUri" mapstructure:"NotificationUri"`AccessType              AccessType             `json:"accessType,omitempty" yaml:"accessType" bson:"accessType" mapstructure:"AccessType"`RatType                 RatType                `json:"ratType,omitempty" yaml:"ratType" bson:"ratType" mapstructure:"RatType"`ServingNetwork          *NetworkId             `json:"servingNetwork,omitempty" yaml:"servingNetwork" bson:"servingNetwork" mapstructure:"ServingNetwork"`UserLocationInfo        *UserLocation          `json:"userLocationInfo,omitempty" yaml:"userLocationInfo" bson:"userLocationInfo" mapstructure:"UserLocationInfo"`UeTimeZone              string                 `json:"ueTimeZone,omitempty" yaml:"ueTimeZone" bson:"ueTimeZone" mapstructure:"UeTimeZone"`Pei                     string                 `json:"pei,omitempty" yaml:"pei" bson:"pei" mapstructure:"Pei"`Ipv4Address             string                 `json:"ipv4Address,omitempty" yaml:"ipv4Address" bson:"ipv4Address" mapstructure:"Ipv4Address"`Ipv6AddressPrefix       string                 `json:"ipv6AddressPrefix,omitempty" yaml:"ipv6AddressPrefix" bson:"ipv6AddressPrefix" mapstructure:"Ipv6AddressPrefix"`// Indicates the IPv4 address domainIpDomain     string                `json:"ipDomain,omitempty" yaml:"ipDomain" bson:"ipDomain" mapstructure:"IpDomain"`SubsSessAmbr *Ambr                 `json:"subsSessAmbr,omitempty" yaml:"subsSessAmbr" bson:"subsSessAmbr" mapstructure:"SubsSessAmbr"`SubsDefQos   *SubscribedDefaultQos `json:"subsDefQos,omitempty" yaml:"subsDefQos" bson:"subsDefQos" mapstructure:"SubsDefQos"`// Contains the number of supported packet filter for signalled QoS rules.NumOfPackFilter int32 `json:"numOfPackFilter,omitempty" yaml:"numOfPackFilter" bson:"numOfPackFilter" mapstructure:"NumOfPackFilter"`// If it is included and set to true, the online charging is applied to the PDU session.Online bool `json:"online,omitempty" yaml:"online" bson:"online" mapstructure:"Online"`// If it is included and set to true, the offline charging is applied to the PDU session.Offline bool `json:"offline,omitempty" yaml:"offline" bson:"offline" mapstructure:"Offline"`// If it is included and set to true, the 3GPP PS Data Off is activated by the UE.Var3gppPsDataOffStatus bool `json:"3gppPsDataOffStatus,omitempty" yaml:"3gppPsDataOffStatus" bson:"3gppPsDataOffStatus" mapstructure:"Var3gppPsDataOffStatus"`// If it is included and set to true, the reflective QoS is supported by the UE.RefQosIndication bool               `json:"refQosIndication,omitempty" yaml:"refQosIndication" bson:"refQosIndication" mapstructure:"RefQosIndication"`TraceReq         *TraceData         `json:"traceReq,omitempty" yaml:"traceReq" bson:"traceReq" mapstructure:"TraceReq"`SliceInfo        *Snssai            `json:"sliceInfo" yaml:"sliceInfo" bson:"sliceInfo" mapstructure:"SliceInfo"`QosFlowUsage     QosFlowUsage       `json:"qosFlowUsage,omitempty" yaml:"qosFlowUsage" bson:"qosFlowUsage" mapstructure:"QosFlowUsage"`ServNfId         *ServingNfIdentity `json:"servNfId,omitempty" yaml:"servNfId" bson:"servNfId" mapstructure:"ServNfId"`SuppFeat         string             `json:"suppFeat,omitempty" yaml:"suppFeat" bson:"suppFeat" mapstructure:"SuppFeat"`SmfId            string             `json:"smfId,omitempty" yaml:"smfId" bson:"smfId" mapstructure:"SmfId"`RecoveryTime     *time.Time         `json:"recoveryTime,omitempty" yaml:"recoveryTime" bson:"recoveryTime" mapstructure:"RecoveryTime"`
}// https://github.com/free5gc/openapi/blob/v1.0.8/models/model_sm_policy_decision.go
type SmPolicyDecision struct {// A map of Sessionrules with the content being the SessionRule as described in subclause 5.6.2.7.SessRules map[string]*SessionRule `json:"sessRules,omitempty" yaml:"sessRules" bson:"sessRules" mapstructure:"SessRules"`// A map of PCC rules with the content being the PCCRule as described in subclause 5.6.2.6.PccRules map[string]*PccRule `json:"pccRules,omitempty" yaml:"pccRules" bson:"pccRules" mapstructure:"PccRules"`// If it is included and set to true, it indicates the P-CSCF Restoration is requested.PcscfRestIndication bool `json:"pcscfRestIndication,omitempty" yaml:"pcscfRestIndication" bson:"pcscfRestIndication" mapstructure:"PcscfRestIndication"`// Map of QoS data policy decisions.QosDecs map[string]*QosData `json:"qosDecs,omitempty" yaml:"qosDecs" bson:"qosDecs" mapstructure:"QosDecs"`// Map of Charging data policy decisions.ChgDecs      map[string]*ChargingData `json:"chgDecs,omitempty" yaml:"chgDecs" bson:"chgDecs" mapstructure:"ChgDecs"`ChargingInfo *ChargingInformation     `json:"chargingInfo,omitempty" yaml:"chargingInfo" bson:"chargingInfo" mapstructure:"ChargingInfo"`// Map of Traffic Control data policy decisions.TraffContDecs map[string]*TrafficControlData `json:"traffContDecs,omitempty" yaml:"traffContDecs" bson:"traffContDecs" mapstructure:"TraffContDecs"`// Map of Usage Monitoring data policy decisions.UmDecs map[string]*UsageMonitoringData `json:"umDecs,omitempty" yaml:"umDecs" bson:"umDecs" mapstructure:"UmDecs"`// Map of QoS characteristics for non standard 5QIs. This map uses the 5QI values as keys.QosChars           map[string]*QosCharacteristics `json:"qosChars,omitempty" yaml:"qosChars" bson:"qosChars" mapstructure:"QosChars"`ReflectiveQoSTimer int32                          `json:"reflectiveQoSTimer,omitempty" yaml:"reflectiveQoSTimer" bson:"reflectiveQoSTimer" mapstructure:"ReflectiveQoSTimer"`// A map of condition data with the content being as described in subclause 5.6.2.9.Conds            map[string]*ConditionData `json:"conds,omitempty" yaml:"conds" bson:"conds" mapstructure:"Conds"`RevalidationTime *time.Time                `json:"revalidationTime,omitempty" yaml:"revalidationTime" bson:"revalidationTime" mapstructure:"RevalidationTime"`// Indicates the offline charging is applicable to the PDU session or PCC rule.Offline bool `json:"offline,omitempty" yaml:"offline" bson:"offline" mapstructure:"Offline"`// Indicates the online charging is applicable to the PDU session or PCC rule.Online bool `json:"online,omitempty" yaml:"online" bson:"online" mapstructure:"Online"`// Defines the policy control request triggers subscribed by the PCF.PolicyCtrlReqTriggers []PolicyControlRequestTrigger `json:"policyCtrlReqTriggers,omitempty" yaml:"policyCtrlReqTriggers" bson:"policyCtrlReqTriggers" mapstructure:"PolicyCtrlReqTriggers"`// Defines the last list of rule control data requested by the PCF.LastReqRuleData  []RequestedRuleData `json:"lastReqRuleData,omitempty" yaml:"lastReqRuleData" bson:"lastReqRuleData" mapstructure:"LastReqRuleData"`LastReqUsageData *RequestedUsageData `json:"lastReqUsageData,omitempty" yaml:"lastReqUsageData" bson:"lastReqUsageData" mapstructure:"LastReqUsageData"`// Map of PRA information.PraInfos     map[string]*PresenceInfoRm `json:"praInfos,omitempty" yaml:"praInfos" bson:"praInfos" mapstructure:"PraInfos"`Ipv4Index    int32                      `json:"ipv4Index,omitempty" yaml:"ipv4Index" bson:"ipv4Index" mapstructure:"Ipv4Index"`Ipv6Index    int32                      `json:"ipv6Index,omitempty" yaml:"ipv6Index" bson:"ipv6Index" mapstructure:"Ipv6Index"`QosFlowUsage QosFlowUsage               `json:"qosFlowUsage,omitempty" yaml:"qosFlowUsage" bson:"qosFlowUsage" mapstructure:"QosFlowUsage"`SuppFeat     string                     `json:"suppFeat,omitempty" yaml:"suppFeat" bson:"suppFeat" mapstructure:"SuppFeat"`
}// https://github.com/free5gc/openapi/blob/v1.0.8/models/model_pcc_rule.go
type PccRule struct {// An array of IP flow packet filter information.FlowInfos []FlowInformation `json:"flowInfos,omitempty" yaml:"flowInfos" bson:"flowInfos" mapstructure:"FlowInfos"`// A reference to the application detection filter configured at the UPF.AppId string `json:"appId,omitempty" yaml:"appId" bson:"appId" mapstructure:"AppId"`// Represents the content version of some content.ContVer int32 `json:"contVer,omitempty" yaml:"contVer" bson:"contVer" mapstructure:"ContVer"`// Univocally identifies the PCC rule within a PDU session.PccRuleId     string        `json:"pccRuleId" yaml:"pccRuleId" bson:"pccRuleId" mapstructure:"PccRuleId"`Precedence    int32         `json:"precedence,omitempty" yaml:"precedence" bson:"precedence" mapstructure:"Precedence"`AfSigProtocol AfSigProtocol `json:"afSigProtocol,omitempty" yaml:"afSigProtocol" bson:"afSigProtocol" mapstructure:"AfSigProtocol"`// Indication of application relocation possibility.AppReloc bool `json:"appReloc,omitempty" yaml:"appReloc" bson:"appReloc" mapstructure:"AppReloc"`// A reference to the QoSData policy type decision type. It is the qosId described in subclause 5.6.2.8. (NOTE)RefQosData []string `json:"refQosData,omitempty" yaml:"refQosData" bson:"refQosData" mapstructure:"RefQosData"`// A reference to the TrafficControlData policy decision type. It is the tcId described in subclause 5.6.2.10. (NOTE)RefTcData []string `json:"refTcData,omitempty" yaml:"refTcData" bson:"refTcData" mapstructure:"RefTcData"`// A reference to the ChargingData policy decision type. It is the chgId described in subclause 5.6.2.11. (NOTE)RefChgData []string `json:"refChgData,omitempty" yaml:"refChgData" bson:"refChgData" mapstructure:"RefChgData"`// A reference to UsageMonitoringData policy decision type. It is the umId described in subclause 5.6.2.12. (NOTE)RefUmData []string `json:"refUmData,omitempty" yaml:"refUmData" bson:"refUmData" mapstructure:"RefUmData"`// A reference to the condition data. It is the condId described in subclause 5.6.2.9.RefCondData string `json:"refCondData,omitempty" yaml:"refCondData" bson:"refCondData" mapstructure:"RefCondData"`
}// https://github.com/free5gc/openapi/blob/v1.0.8/models/model_session_rule.go
type SessionRule struct {AuthSessAmbr *Ambr                 `json:"authSessAmbr,omitempty" yaml:"authSessAmbr" bson:"authSessAmbr" mapstructure:"AuthSessAmbr"`AuthDefQos   *AuthorizedDefaultQos `json:"authDefQos,omitempty" yaml:"authDefQos" bson:"authDefQos" mapstructure:"AuthDefQos"`// Univocally identifies the session rule within a PDU session.SessRuleId string `json:"sessRuleId" yaml:"sessRuleId" bson:"sessRuleId" mapstructure:"SessRuleId"`// A reference to UsageMonitoringData policy decision type. It is the umId described in subclause 5.6.2.12.RefUmData string `json:"refUmData,omitempty" yaml:"refUmData" bson:"refUmData" mapstructure:"RefUmData"`// A reference to the condition data. It is the condId described in subclause 5.6.2.9.RefCondData string `json:"refCondData,omitempty" yaml:"refCondData" bson:"refCondData" mapstructure:"RefCondData"`
}

与AMPolicy类似,想去内存里的context看看有没有旧的smPopliy,有的话删掉delete(ue.SmPolicyData, smPolicyID),然后创建新的ue.NewUeSmPolicyData(smPolicyID, request, &smData)。这以后,就要开始做一系列复杂的决策, 包括但不限于指定适用的Session rules和PCC rules,从数据库获取QoS流规则和流量控制规则并决定流量控制、收费、和QoS参数等。决策的复杂性很大程度上导致了CREATE操作的复杂性——太多东西要决定了。

// https://github.com/free5gc/pcf/blob/v1.2.5/internal/sbi/processor/smpolicy.go#L28C1-L484C2
func (p *Processor) HandleCreateSmPolicyRequest(c *gin.Context, request models.SmPolicyContextData) {// set up pcf context, uw context, udr client ......var smData models.SmPolicyDatasmPolicyID := fmt.Sprintf("%s-%d", ue.Supi, request.PduSessionId)smPolicyData := ue.SmPolicyData[smPolicyID]  // 这个`smPolicyData`是`UeSmPolicyData`类型if smPolicyData == nil || smPolicyData.SmPolicyData == nil {param := Nudr_DataRepository.PolicyDataUesUeIdSmDataGetParamOpts{Snssai: optional.NewInterface(util.MarshToJsonString(*request.SliceInfo)),Dnn:    optional.NewString(request.Dnn),}smData, response, err1 = client.DefaultApi.PolicyDataUesUeIdSmDataGet(ctx, ue.Supi, &param)} else {smData = *smPolicyData.SmPolicyData}if smPolicyData != nil {delete(ue.SmPolicyData, smPolicyID)  // 删掉旧的smPolicy}smPolicyData = ue.NewUeSmPolicyData(smPolicyID, request, &smData)  // 创建新的smPolicy// 根据SMF发过来的请求以及数据库中的数据进行Policy Decisiondecision := models.SmPolicyDecision{SessRules:     make(map[string]*models.SessionRule),PccRules:      make(map[string]*models.PccRule),TraffContDecs: make(map[string]*models.TrafficControlData),}// decide session rulesSessRuleId := fmt.Sprintf("SessRuleId-%d", request.PduSessionId)sessRule := models.SessionRule{AuthSessAmbr: request.SubsSessAmbr,SessRuleId:   SessRuleId,}defQos := request.SubsDefQosif defQos != nil {sessRule.AuthDefQos = &models.AuthorizedDefaultQos{Var5qi:        defQos.Var5qi,Arp:           defQos.Arp,PriorityLevel: defQos.PriorityLevel,}}decision.SessRules[SessRuleId] = &sessRule// make data network related decisionsdnnData := util.GetSMPolicyDnnData(smData, request.SliceInfo, request.Dnn)if dnnData != nil {decision.Online = dnnData.Onlinedecision.Offline = dnnData.Offline// ......} else {decision.Online = request.Onlinedecision.Offline = request.Offline}// make QoS related decisionsfilter := bson.M{"ueId": ue.Supi, "snssai": util.SnssaiModelsToHex(*request.SliceInfo), "dnn": request.Dnn}qosFlowInterface, err := mongoapi.RestfulAPIGetMany(qosFlowDataColl, filter, queryStrength)for _, qosFlow := range qosFlowInterface {qosData := newQosDataWithQosFlowMap(qosFlow)if decision.QosDecs == nil {decision.QosDecs = make(map[string]*models.QosData)}decision.QosDecs[qosData.QosId] = qosData}flowRulesInterface, err := mongoapi.RestfulAPIGetMany(flowRuleDataColl, filter, queryStrength)// decide PCC rulespcc := util.CreateDefaultPccRules(smPolicyData.PccRuleIdGenerator)smPolicyData.PccRuleIdGenerator++filterCharging := bson.M{"ueId":   ue.Supi,"snssai": util.SnssaiModelsToHex(*request.SliceInfo),"dnn":    "","filter": "",}chargingInterface, err := mongoapi.RestfulAPIGetOne(chargingDataColl, filterCharging, queryStrength)if err != nil {util.SetPccRuleRelatedData(&decision, pcc, nil, nil, nil, nil)} else if chargingInterface != nil {rg, err1 := p.Context().RatingGroupIdGenerator.Allocate()chgData := &models.ChargingData{ChgId:          util.GetChgId(smPolicyData.ChargingIdGenerator),RatingGroup:    int32(rg),ReportingLevel: models.ReportingLevel_RAT_GR_LEVEL,MeteringMethod: models.MeteringMethod_VOLUME,}switch chargingInterface["chargingMethod"].(string) {case "Online":chgData.Online = truechgData.Offline = falsecase "Offline":chgData.Online = falsechgData.Offline = true}util.SetPccRuleRelatedData(&decision, pcc, nil, nil, chgData, nil)chargingInterface["ratingGroup"] = chgData.RatingGroupmongoapi.RestfulAPIPutOne(chargingDataColl, chargingInterface, chargingInterface, queryStrength)if ue.RatingGroupData == nil {ue.RatingGroupData = make(map[string][]int32)}ue.RatingGroupData[smPolicyID] = append(ue.RatingGroupData[smPolicyID], chgData.RatingGroup)smPolicyData.ChargingIdGenerator++}for i, flowRule := range flowRulesInterface {precedence := int32(flowRule["precedence"].(float64))if val, ok := flowRule["filter"].(string); ok {tokens := strings.Split(val, " ")FlowDescription := flowdesc.NewIPFilterRule()// set FlowDescription attributes ......FlowDescriptionStr, err = flowdesc.Encode(FlowDescription)pccRule := util.CreatePccRule(smPolicyData.PccRuleIdGenerator, precedence, []models.FlowInformation{{FlowDescription: FlowDescriptionStr,FlowDirection:   models.FlowDirectionRm_DOWNLINK,},}, "")filterCharging := bson.M{"ueId":   ue.Supi,"snssai": util.SnssaiModelsToHex(*request.SliceInfo),"dnn":    request.Dnn,"filter": val,}var chargingInterface map[string]interface{}chargingInterface, err = mongoapi.RestfulAPIGetOne(chargingDataColl, filterCharging, 2)if err != nil {logger.SmPolicyLog.Errorf("Fail to get charging data to mongoDB err: %+v", err)} else {rg, err1 := p.Context().RatingGroupIdGenerator.Allocate()chgData := &models.ChargingData{ChgId:          util.GetChgId(smPolicyData.ChargingIdGenerator),RatingGroup:    int32(rg),ReportingLevel: models.ReportingLevel_RAT_GR_LEVEL,MeteringMethod: models.MeteringMethod_VOLUME,}switch chargingInterface["chargingMethod"].(string) {case "Online":chgData.Online = truechgData.Offline = falsecase "Offline":chgData.Online = falsechgData.Offline = true}if decision.ChgDecs == nil {decision.ChgDecs = make(map[string]*models.ChargingData)}chargingInterface["ratingGroup"] = chgData.RatingGroupif _, err = mongoapi.RestfulAPIPutOne(chargingDataColl, chargingInterface, chargingInterface, queryStrength); err != nil {logger.SmPolicyLog.Errorf("Fail to put charging data to mongoDB err: %+v", err)} else {util.SetPccRuleRelatedData(&decision, pccRule, nil, nil, chgData, nil)smPolicyData.ChargingIdGenerator++}if ue.RatingGroupData == nil {ue.RatingGroupData = make(map[string][]int32)}ue.RatingGroupData[smPolicyID] = append(ue.RatingGroupData[smPolicyID], chgData.RatingGroup)}qosRef := strconv.Itoa(int(flowRule["qosRef"].(float64)))util.SetPccRuleRelatedByQosRef(&decision, pccRule, qosRef)smPolicyData.PccRuleIdGenerator++}}requestSuppFeat, err := openapi.NewSupportedFeature(request.SuppFeat)decision.SuppFeat = pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_SMPOLICYCONTROL].NegotiateWith(requestSuppFeat).String()decision.QosFlowUsage = request.QosFlowUsage// TODO: Trigger about UMC, ADC, NetLoc,...decision.PolicyCtrlReqTriggers = util.PolicyControlReqTrigToArray(0x40780f)smPolicyData.PolicyDecision = &decision// Gmake traffica influcence related decisionsreqParam := Nudr_DataRepository.ApplicationDataInfluenceDataGetParamOpts{Dnns:             optional.NewInterface([]string{request.Dnn}),Snssais:          optional.NewInterface(util.MarshToJsonString([]models.Snssai{*request.SliceInfo})),InternalGroupIds: optional.NewInterface(request.InterGrpIds),Supis:            optional.NewInterface([]string{request.Supi}),}trafficInfluDatas, resp, err := udrClient.InfluenceDataApi.ApplicationDataInfluenceDataGet(ctx, &reqParam)if len(trafficInfluDatas) != 0 {// UE identity in UDR appData and apply appData to sm poliocyvar precedence int32 = 23for _, tiData := range trafficInfluDatas {pccRule := util.CreatePccRule(smPolicyData.PccRuleIdGenerator, precedence, nil, tiData.AfAppId)util.SetSmPolicyDecisionByTrafficInfluData(&decision, pccRule, tiData)influenceID := getInfluenceID(tiData.ResUri)if influenceID != "" {smPolicyData.InfluenceDataToPccRule[influenceID] = pccRule.PccRuleId}smPolicyData.PccRuleIdGenerator++if precedence < Precedence_Maximum {precedence++}}}// Subscribe to Traffic Influence Data in UDRsubscriptionID, problemDetail, err := p.Consumer().CreateInfluenceDataSubscription(ue, request)smPolicyData.SubscriptionID = subscriptionIDc.JSON(http.StatusCreated, decision)
}

UPDATE操作与CREATE操作类似,在此略过。

PolicyAuthorization

从名字中只能看出来PolicyAuthorization好像是想给某个policy授权?但实际上,PolicyAuthorization更像是一个AF(Application Function)与PCF之间的接口,AF通过这个接口发起请求,PCF为这个应用分配合适的资源和策略。这些第三方应用包括视频流媒体服务、VoIP通话、在线游戏、企业内线服务等。

Application Function (AF): Element offering application(s) that use PDU session resources

img

PolicyAuthorizationSMPolicyControl关系相当密切:当AF通过PolicyAuthorization请求资源时,PCF会创建相应的PCC Rules,通过SMPolicyControl将这些规则下发给SMF执行,且在AppSession和SmPolicy之间建立映射关系。PolicyAuthorization的GET和DELETE操作都与SMPolicy异曲同工:GET操作根据appSessionId直接从Context找到数据返回,DELETE操作除了要删除Context中的数据delete(smPolicy.AppSessions, appSessionId); pcfSelf.AppSessionPool.Delete(appSessionId)还需要删除相关的PCC Rules并通知SMF删除事宜。

// https://github.com/free5gc/pcf/blob/main/internal/sbi/processor/policyauthorization.go#L499
func (p *Processor) HandleGetAppSessionContext(c *gin.Context, appSessionId string) {pcfSelf := p.Context()var appSession *pcf_context.AppSessionDataval, ok := pcfSelf.AppSessionPool.Load(appSessionId)appSession = val.(*pcf_context.AppSessionData)c.JSON(http.StatusOK, appSession.AppSessionContext)
}// https://github.com/free5gc/pcf/blob/main/internal/sbi/processor/policyauthorization.go#L438
func (p *Processor) HandleDeleteAppSessionContext(c *gin.Context, appSessionId string,eventsSubscReqData *models.EventsSubscReqData,
) {pcfSelf := p.Context()var appSession *pcf_context.AppSessionDataif val, ok := pcfSelf.AppSessionPool.Load(appSessionId); ok {appSession = val.(*pcf_context.AppSessionData)}// Remove related pcc rule resourcesmPolicy := appSession.SmPolicyDatadeletedSmPolicyDec := models.SmPolicyDecision{}for _, pccRuleID := range appSession.RelatedPccRuleIds {smPolicy.RemovePccRule(pccRuleID, &deletedSmPolicyDec)}delete(smPolicy.AppSessions, appSessionId)pcfSelf.AppSessionPool.Delete(appSessionId)smPolicy.ArrangeExistEventSubscription()// Notify SMF About Pcc Rule removalnotification := models.SmPolicyNotification{ResourceUri:      util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyID),SmPolicyDecision: &deletedSmPolicyDec,}go p.SendSMPolicyUpdateNotification(smPolicy.PolicyContext.NotificationUri, &notification)c.JSON(http.StatusNoContent, nil)
}
AppSessionContext, AppSessionContextReqData

// Represents an Individual Application Session Context resource.
type AppSessionContext struct {AscReqData  *AppSessionContextReqData  `json:"ascReqData,omitempty" yaml:"ascReqData" bson:"ascReqData" mapstructure:"AscReqData"`AscRespData *AppSessionContextRespData `json:"ascRespData,omitempty" yaml:"ascRespData" bson:"ascRespData" mapstructure:"AscRespData"`EvsNotif    *EventsNotification        `json:"evsNotif,omitempty" yaml:"evsNotif" bson:"evsNotif" mapstructure:"EvsNotif"`
}// Identifies the service requirements of an Individual Application Session Context.
type AppSessionContextReqData struct {// Contains an AF application identifier.AfAppId   string                `json:"afAppId,omitempty" yaml:"afAppId" bson:"afAppId" mapstructure:"AfAppId"`AfRoutReq *AfRoutingRequirement `json:"afRoutReq,omitempty" yaml:"afRoutReq" bson:"afRoutReq" mapstructure:"AfRoutReq"`// Contains an identity of an application service provider.AspId string `json:"aspId,omitempty" yaml:"aspId" bson:"aspId" mapstructure:"AspId"`// string identifying a BDT Reference ID as defined in subclause 5.3.3 of 3GPP TS 29.154.BdtRefId      string                    `json:"bdtRefId,omitempty" yaml:"bdtRefId" bson:"bdtRefId" mapstructure:"BdtRefId"`Dnn           string                    `json:"dnn,omitempty" yaml:"dnn" bson:"dnn" mapstructure:"Dnn"`EvSubsc       *EventsSubscReqData       `json:"evSubsc,omitempty" yaml:"evSubsc" bson:"evSubsc" mapstructure:"EvSubsc"`MedComponents map[string]MediaComponent `json:"medComponents,omitempty" yaml:"medComponents" bson:"medComponents" mapstructure:"MedComponents"`IpDomain      string                    `json:"ipDomain,omitempty" yaml:"ipDomain" bson:"ipDomain" mapstructure:"IpDomain"`// indication of MPS service requestMpsId string `json:"mpsId,omitempty" yaml:"mpsId" bson:"mpsId" mapstructure:"MpsId"`// string providing an URI formatted according to IETF RFC 3986.NotifUri  string  `json:"notifUri" yaml:"notifUri" bson:"notifUri" mapstructure:"NotifUri"`SliceInfo *Snssai `json:"sliceInfo,omitempty" yaml:"sliceInfo" bson:"sliceInfo" mapstructure:"SliceInfo"`// Contains an identity of a sponsor.SponId     string           `json:"sponId,omitempty" yaml:"sponId" bson:"sponId" mapstructure:"SponId"`SponStatus SponsoringStatus `json:"sponStatus,omitempty" yaml:"sponStatus" bson:"sponStatus" mapstructure:"SponStatus"`Supi       string           `json:"supi,omitempty" yaml:"supi" bson:"supi" mapstructure:"Supi"`Gpsi       string           `json:"gpsi,omitempty" yaml:"gpsi" bson:"gpsi" mapstructure:"Gpsi"`SuppFeat   string           `json:"suppFeat" yaml:"suppFeat" bson:"suppFeat" mapstructure:"SuppFeat"`UeIpv4     string           `json:"ueIpv4,omitempty" yaml:"ueIpv4" bson:"ueIpv4" mapstructure:"UeIpv4"`UeIpv6     string           `json:"ueIpv6,omitempty" yaml:"ueIpv6" bson:"ueIpv6" mapstructure:"UeIpv6"`UeMac      string           `json:"ueMac,omitempty" yaml:"ueMac" bson:"ueMac" mapstructure:"UeMac"`
}// https://github.com/free5gc/openapi/blob/main/models/model_media_component.go
// Identifies a media component.
type MediaComponent struct {// Contains an AF application identifier.AfAppId   string                `json:"afAppId,omitempty" yaml:"afAppId" bson:"afAppId" mapstructure:"AfAppId"`AfRoutReq *AfRoutingRequirement `json:"afRoutReq,omitempty" yaml:"afRoutReq" bson:"afRoutReq" mapstructure:"AfRoutReq"`// Represents the content version of some content.ContVer     int32                        `json:"contVer,omitempty" yaml:"contVer" bson:"contVer" mapstructure:"ContVer"`Codecs      []string                     `json:"codecs,omitempty" yaml:"codecs" bson:"codecs" mapstructure:"Codecs"`FStatus     FlowStatus                   `json:"fStatus,omitempty" yaml:"fStatus" bson:"fStatus" mapstructure:"FStatus"`MarBwDl     string                       `json:"marBwDl,omitempty" yaml:"marBwDl" bson:"marBwDl" mapstructure:"MarBwDl"`MarBwUl     string                       `json:"marBwUl,omitempty" yaml:"marBwUl" bson:"marBwUl" mapstructure:"MarBwUl"`MedCompN    int32                        `json:"medCompN" yaml:"medCompN" bson:"medCompN" mapstructure:"MedCompN"`MedSubComps map[string]MediaSubComponent `json:"medSubComps,omitempty" yaml:"medSubComps" bson:"medSubComps" mapstructure:"MedSubComps"`MedType     MediaType                    `json:"medType,omitempty" yaml:"medType" bson:"medType" mapstructure:"MedType"`MirBwDl     string                       `json:"mirBwDl,omitempty" yaml:"mirBwDl" bson:"mirBwDl" mapstructure:"MirBwDl"`MirBwUl     string                       `json:"mirBwUl,omitempty" yaml:"mirBwUl" bson:"mirBwUl" mapstructure:"MirBwUl"`ResPrio     ReservPriority               `json:"resPrio,omitempty" yaml:"resPrio" bson:"resPrio" mapstructure:"ResPrio"`
}// https://github.com/free5gc/openapi/blob/main/models/model_media_sub_component.go
// Identifies a media subcomponent
type MediaSubComponent struct {EthfDescs []EthFlowDescription `json:"ethfDescs,omitempty" yaml:"ethfDescs" bson:"ethfDescs" mapstructure:"EthfDescs"`FNum      int32                `json:"fNum" yaml:"fNum" bson:"fNum" mapstructure:"FNum"`FDescs    []string             `json:"fDescs,omitempty" yaml:"fDescs" bson:"fDescs" mapstructure:"FDescs"`FStatus   FlowStatus           `json:"fStatus,omitempty" yaml:"fStatus" bson:"fStatus" mapstructure:"FStatus"`MarBwDl   string               `json:"marBwDl,omitempty" yaml:"marBwDl" bson:"marBwDl" mapstructure:"MarBwDl"`MarBwUl   string               `json:"marBwUl,omitempty" yaml:"marBwUl" bson:"marBwUl" mapstructure:"MarBwUl"`// 2-octet string, where each octet is encoded in hexadecimal representation. The first octet contains the IPv4 Type-of-Service or the IPv6 Traffic-Class field and the second octet contains the ToS/Traffic Class mask field.TosTrCl   string    `json:"tosTrCl,omitempty" yaml:"tosTrCl" bson:"tosTrCl" mapstructure:"TosTrCl"`FlowUsage FlowUsage `json:"flowUsage,omitempty" yaml:"flowUsage" bson:"flowUsage" mapstructure:"FlowUsage"`
}
与`NpcfSMPolicyControl`一样,CREATE方法对应的处理函数又长又琐碎:首先将`appSession`与`ueSmPolicyData`进行绑定,然后是PCF的核心任务,也就是处理[媒体组件(Media Components)](https://github.com/free5gc/openapi/blob/main/models/model_media_component.go)——为每个媒体组件创建或更新PCC规则、设置QoS参数、处理流量路由信息,然后是处理事件订阅——这些事件订阅允许AF获知网络状态的变化,从而可以相应地调整其应用行为或服务质量要求(比如当接入类型发生变化时,AF可能需要调整视频流的比特率),处理赞助连接(Sponsored Connectivity,可以先简单理解为[定向流量](https://baike.baidu.com/item/%E5%AE%9A%E5%90%91%E6%B5%81%E9%87%8F/385830))信息,最后是创建`appSession`ID存储`appSession`数据,并向SMF发送策略更新通知。
// https://github.com/free5gc/pcf/blob/main/internal/sbi/processor/policyauthorization.go#L154
// Radically simplified!
func (p *Processor) postAppSessCtxProcedure(appSessCtx *models.AppSessionContext) (*models.AppSessionContext, *models.ProblemDetails,
) {// Initial BDT policy indication(the only one which is not related to session)if appSessCtx.ascReqData.BdtRefId != "" {p.handleBDTPolicyInd(pcf_context, appSessCtx)pcfSelf.AppSessionPool.Store(ascReqData.BdtRefId, appSessCtx)return appSessCtx, nil}ueSmPolicyData := pcfSelf.SessionBinding(appSessCtx.ascReqData)// Handle Pcc rulesfor _, medComp := range ascReqData.MedComponents {pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, appID)qosData := util.CreateQosData(smPolicy.PccRuleIdGenerator, var5qi, 8)util.SetPccRuleRelatedData(ueSmPolicyData.PolicyDecision, pccRule, nil, &qosData, nil, nil)} else {// update pccRule's qosfor _, qosID := range pccRule.RefQosData {qosData = *smPolicy.PolicyDecision.QosDecs[qosID]、qosData, ul, dl = updateQosInMedComp(*smPolicy.PolicyDecision.QosDecs[qosID], &medComp)modifyRemainBitRate(smPolicy, &qosData, ul, dl)smPolicy.PolicyDecision.QosDecs[qosData.QosId] = &qosData}}// Initial provisioning of traffic routing informationpccRule := provisioningOfTrafficRoutingInfo(smPolicy, ascReqData.AfAppId, ascReqData.AfRoutReq, "")relatedPccRuleIds := make(map[string]string)key := fmt.Sprintf("appID-%s", ascReqData.AfAppId)relatedPccRuleIds[key] = pccRule.PccRuleId// Event SubscriptioneventSubs := make(map[models.AfEvent]models.AfNotifMethod)for _, subs := range ascReqData.EvSubsc.Events {eventSubs[subs.Event] = subs.NotifMethodvar trig models.PolicyControlRequestTriggerswitch subs.Event {case models.AfEvent_ACCESS_TYPE_CHANGE:trig = models.PolicyControlRequestTrigger_AC_TY_CH// more cases ...default:logger.PolicyAuthLog.Warn("AF Event is unknown")continue}if !util.CheckPolicyControlReqTrig(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) {smPolicy.PolicyDecision.PolicyCtrlReqTriggers = append(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig)}   }// Initial provisioning of sponsored connectivity informationumID := util.GetUmId(ascReqData.AspId, ascReqData.SponId)umData := extractUmData(umID, eventSubs, ascReqData.EvSubsc.UsgThres)handleSponsoredConnectivityInformation(smPolicy, relatedPccRuleIds, ascReqData.AspId,ascReqData.SponId, ascReqData.SponStatus, umData, &updateSMpolicy)// Allocate App Session IdappSessID := ue.AllocUeAppSessionId(pcfSelf)// Associate App Session to SMPolicysmPolicy.AppSessions[appSessID] = truedata := pcf_context.AppSessionData{AppSessionId:      appSessID,AppSessionContext: appSessCtx,SmPolicyData:      smPolicy,}if len(relatedPccRuleIds) > 0 {data.RelatedPccRuleIds = relatedPccRuleIdsdata.PccRuleIdMapToCompId = reverseStringMap(relatedPccRuleIds)}appSessCtx.EvsNotif = &models.EventsNotification{}// Set Event Subsciption related Data ...pcfSelf.AppSessionPool.Store(appSessID, &data)// Send Notification to SMFgo p.SendSMPolicyUpdateNotification(smPolicy.PolicyContext.NotificationUri, &notification)return appSessCtx, nil
}

至此我研究了一遍PCF的机制及其源代码,但我总还有一些云里雾里的感觉。我认为这是因为PCF深度介入AMF以及SMF,尤其是SMF。所以想要全面理解PCF就必须等到研究完AMF和SMF才能做到,至少要知道PCF所指定的policy是怎么被应用和实施的。所以下文先从SMF开始。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/832364.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

遥感大数据智能分析与应用

在数字化和信息化时代,遥感技术已经成为获取地球表面信息的重要手段。随着遥感数据量的激增,如何高效、智能地分析和应用这些数据,成为了一个亟待解决的问题。本文将探讨遥感大数据智能分析的现状与未来趋势。遥感大数据的挑战与机遇遥感数据正以前所未有的速度增长,这些数…

GMES101 作业一

一共就是求两个矩阵一个旋转矩阵一个投射矩阵 旋转矩阵 旋转矩阵还能第一时间反应过来去找公式 投射矩阵 投射矩阵就完全不记得了,又去看了一遍视频,终于完全理解了投射矩阵究竟是个啥意思 原来还要自己算\[ M_{persp\to ortho}= \begin{matrix} n&0&0&0 \\ 0&am…

waypoint常常被翻译成航路点

参考资料:2023-端到端自动驾驶系统研究综述-陈妍妍 2024-EMMA: End-to-End Multimodal Model for Autonomous Driving

作业四

作业一 要求: ▪ 熟练掌握 Selenium 查找 HTML 元素、爬取 Ajax 网页数据、等待 HTML 元素等内 容。 ▪ 使用 Selenium 框架+ MySQL 数据库存储技术路线爬取“沪深 A 股”、“上证 A 股”、 “深证 A 股”3 个板块的股票数据信息。 o 候选网站:东方财富网: http://quote.eas…

ATE测试 - STDF文件分析 - Excel报表格式探讨

1、转换对象:STDF文件 2、适用人员:TE 或 解决方案人员 或 需要对测试项TestItem原始测试值进行分析的 2、Excel格式:如下示意图4、局限性:Excel一个sheet中,列数最大不能超过16384列,行数最大不能超过1048576行,因此这种格式对于超过16384颗Die的文件就无法生成Excel文…

实验一:百度机器翻译SDK实验(2024.11.15日完成)

实验一:百度机器翻译SDK实验(2024.11.15日完成)任务一:下载配置百度翻译Java相关库及环境(占10%)。任务二:了解百度翻译相关功能并进行总结,包括文本翻译-通用版和文本翻译-词典版(占20%)。任务三:完成百度翻译相关功能代码并测试调用,要求可以实现中文翻译成英文,…

2024.11.12 NOIP模拟 - 模拟赛记录

Preface 一套烂题。 T1 一眼搬的 CF(赛后十秒就找到原题了),只搬 idea 就算了,根本不设置部分分,大样例给的更是一坨(数据范围给的 \(10^{15}\),1 2 10 72 121 算什么大样例?),甚至最后的题解都是直接复制的洛谷。 T2 稍好,除了实数运算稍微恶心一点,其它都没什么。…

数据采集与融合技术作业四

目录作业①实验要求及结果心得体会作业②实验要求及结果心得体会作业③实验要求及结果心得体会码云连接作业① 实验要求及结果要求 熟练掌握 Selenium 查找HTML元素、爬取Ajax网页数据、等待HTML元素等内容。 使用Selenium框架+ MySQL数据库存储技术路线爬取“沪深A股”、“上证…

[转贴]在前端如何玩转 Word 文档

在日常工作中,大部分人都会使用 Microsoft Office Word、WPS 或 macOS Pages 等文字处理程序进行 Word 文档处理。除了使用上述的文字处理程序之外,对于 Word 文档来说,还有其他的处理方式么?答案是有的。 接下来阿宝哥将介绍在前端如何玩转 Word 文档,阅读本文之后,你将…

AI之旅:起步即迈出重要一步,博客园与 Chat2DB 达成战略合作

在技术变革的路上,我们不会孤单。我们与博客园的合作,只是一个开始。未来,更多的技术人将加入这场旅程,共同书写AI时代的开发者新篇章。我们希望,这条路上的每一个人,都能够在智能工具与温暖社区的双重支持下,走得更远、飞得更高AI之旅开篇之后的第一篇本准备写一篇简单…

深入理解MySQL索引的底层原理和优化

深入理解MySQL索引的底层原理和优化 1. 什么是索引 索引是帮助MySQL高效获取数据的排好序的数据结构。用于提高查询性能,相当于书的目录。比如我们在读一本书的时候,首先是通过目录来定位到文章的页码,然后通过页码再来快速定位到具体的内容。MySQL中也是一样,在查询数据的…

攻防世界-mfc逆向

文件被加了vmp,静态分析难度很大运行程序 发现是mfc框架程序,根据提示应该在控件里去找,可以用xspy进行分析 发现窗口句柄中有一串密文944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b,并且发现一条特殊的onMsgOnMsg:0464,func= 0x00402170(MFC1.exe+ 0x002170 ),它并不…