Skip to content

IMS Support#317

Open
anaswarac-dac wants to merge 1 commit intoomec-project:mainfrom
5GC-DEV:ims-support
Open

IMS Support#317
anaswarac-dac wants to merge 1 commit intoomec-project:mainfrom
5GC-DEV:ims-support

Conversation

@anaswarac-dac
Copy link
Copy Markdown
Contributor

This PR adds IMS call support for UE in PCF.

Note: - During testing with COTS UEs, IMS PDU session release behavior was observed from UE and needs further analysis.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to add IMS call support in PCF policy authorization by adjusting how PCC/QoS resources are created/selected for media components and by changing PCC/QoS/TC/packet-filter identifier formats.

Changes:

  • Switch PCC rule / QoS / TC / packet-filter IDs to plain numeric strings.
  • Update policy authorization handling to combine MediaSubComponents into a single PCC rule path and send SMF update notifications using a filtered SmPolicyDecision.
  • Add extensive new logging around AppSessionContext processing and PCC/QoS/TC creation.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 10 comments.

File Description
util/pcc_rule.go Changes PCC/QoS/TC/packet-filter identifier formatting to numeric strings.
producer/policyauthorization.go Adds combined MediaSubComponent handling, filtered SMF notifications, and extensive new logs.
context/ue.go Modifies SM policy lookup by IPv4 identifiers and adds logging.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1524 to +1526
if n, err := strconv.Atoi(id); err == nil && int32(n) > maxID {
maxID = int32(n)
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getMaxPccRuleIdNum only considers PCC rule map keys that are pure integers. Before this PR, PCC rule IDs were formatted with a prefix (e.g., PccRuleId-<n>), so after an upgrade existing in-memory decisions may still contain non-numeric keys; those will be ignored here and can cause ID generator collisions. Consider supporting both formats (strip known prefixes before Atoi) or ensuring existing decisions are normalized before calling this.

Suggested change
if n, err := strconv.Atoi(id); err == nil && int32(n) > maxID {
maxID = int32(n)
}
// First, try to parse the ID as a plain integer.
if n, err := strconv.Atoi(id); err == nil {
if int32(n) > maxID {
maxID = int32(n)
}
continue
}
// Fallback: support legacy IDs formatted as "PccRuleId-<n>".
const legacyPrefix = "PccRuleId-"
if strings.HasPrefix(id, legacyPrefix) {
numPart := strings.TrimPrefix(id, legacyPrefix)
if n, err := strconv.Atoi(numPart); err == nil && int32(n) > maxID {
maxID = int32(n)
}
}

Copilot uses AI. Check for mistakes.
Comment on lines 435 to +447
@@ -441,9 +442,12 @@ func (ue *UeContext) SMPolicyFindByIdentifiersIpv4(
if sNssai != nil && !reflect.DeepEqual(sNssai, policyContext.SliceInfo) {
continue
}
return smPolicy
}
logger.CtxLog.Infof("SMPolicy[%s] matched for IPv4: %s", id, v4)
return smPolicy
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SMPolicyFindByIdentifiersIpv4 returns the first SM policy even when the IPv4 (or other identifiers) do not match, because the log+return are outside the if policyContext.Ipv4Address == v4 block. This will break session binding and can associate requests with the wrong PDU session. Move the log+return inside the matching block (after all identifier checks).

Copilot uses AI. Check for mistakes.
Comment on lines 25 to +37
// Get pcc rule Identity(PccRuleId-%d)
func GetPccRuleId(id int32) string {
return fmt.Sprintf("PccRuleId-%d", id)
return fmt.Sprintf("%d", id)
}

// Get qos Identity(QosId-%d)
func GetQosId(id int32) string {
return fmt.Sprintf("QosId-%d", id)
return fmt.Sprintf("%d", id)
}

// Get Traffic Control Identity(TcId-%d)
func GetTcId(id int32) string {
return fmt.Sprintf("TcId-%d", id)
return fmt.Sprintf("%d", id)
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These comments still describe prefixed IDs (e.g., PccRuleId-%d, QosId-%d, TcId-%d) but the functions now return plain numeric strings. Please update the comments so they match the actual ID formats to avoid confusing future callers/debugging.

Copilot uses AI. Check for mistakes.
}

// Find pccRule by AfAppId, otherwise create a new pcc rule
logger.PolicyAuthorizationlog.Debugf("AfAppId", appID)
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Debugf call has an extra argument (appID) but the format string has no formatting verb, which will result in %!(EXTRA ...) output in logs and makes troubleshooting harder. Include %s (or similar) in the format string, or remove the unused argument.

Suggested change
logger.PolicyAuthorizationlog.Debugf("AfAppId", appID)
logger.PolicyAuthorizationlog.Debugf("AfAppId: %s", appID)

Copilot uses AI. Check for mistakes.
Comment on lines +563 to +565
SmPolicyDecision: filteredDecision,
}
decisionJSON, err := json.MarshalIndent(filteredDecision, "", " ")
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updateSMpolicy can be set due to changes outside PCC/QoS/TC (e.g., PolicyCtrlReqTriggers updates when AF events are subscribed), but the notification sends only filteredDecision (PCC/QoS/TC) to the SMF. This can silently drop trigger updates (and any other updated decision fields). Consider sending smPolicy.PolicyDecision, or extend filteredDecision to include all updated fields (at minimum PolicyCtrlReqTriggers).

Suggested change
SmPolicyDecision: filteredDecision,
}
decisionJSON, err := json.MarshalIndent(filteredDecision, "", " ")
SmPolicyDecision: smPolicy.PolicyDecision,
}
decisionJSON, err := json.MarshalIndent(smPolicy.PolicyDecision, "", " ")

Copilot uses AI. Check for mistakes.
Comment on lines +505 to +506
logger.PolicyAuthorizationlog.Infof("AppSession Context: %+v", appSessCtx)
logger.PolicyAuthorizationlog.Infof("SM Policy associated with AppSession [%s]: %+v", appSessID, smPolicy)
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These INFO logs dump entire appSessCtx / smPolicy structs with %+v, which is likely to be extremely large and may include identifiers/policy data that shouldn't be in INFO logs. This also adds avoidable CPU/allocations on every request. Prefer DEBUG level and/or log a small curated summary.

Suggested change
logger.PolicyAuthorizationlog.Infof("AppSession Context: %+v", appSessCtx)
logger.PolicyAuthorizationlog.Infof("SM Policy associated with AppSession [%s]: %+v", appSessID, smPolicy)
logger.PolicyAuthorizationlog.Debugf("AppSession Context: %+v", appSessCtx)
logger.PolicyAuthorizationlog.Debugf("SM Policy associated with AppSession [%s]: %+v", appSessID, smPolicy)

Copilot uses AI. Check for mistakes.
if err != nil {
logger.PolicyAuthorizationlog.Errorf("Failed to marshal SmPolicyDecision: %+v", err)
} else {
logger.PolicyAuthorizationlog.Infof("SmPolicyDecision data: %s", string(decisionJSON))
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marshaling and logging the entire SmPolicyDecision as pretty-printed JSON at INFO level can be very expensive and will generate large logs for normal traffic. Consider gating this behind DEBUG (or a feature flag) and logging only identifiers/counts at INFO.

Suggested change
logger.PolicyAuthorizationlog.Infof("SmPolicyDecision data: %s", string(decisionJSON))
logger.PolicyAuthorizationlog.Debugf("SmPolicyDecision data: %s", string(decisionJSON))

Copilot uses AI. Check for mistakes.
// Get Packet Filter Identity(PackFiltId-%d)
func GetPackFiltId(id int32) string {
return fmt.Sprintf("PackFiltId-%d", id)
// return fmt.Sprintf("PackFiltId-%d", id)
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetPackFiltId still contains a commented-out return of the old ID format. Keeping dead/commented code here makes the intended format unclear; remove the commented line now that numeric IDs are the chosen format.

Suggested change
// return fmt.Sprintf("PackFiltId-%d", id)

Copilot uses AI. Check for mistakes.
ascReqData := appSessCtx.AscReqData
pcfSelf := pcf_context.PCF_Self()

logger.PolicyAuthorizationlog.Infof("Received App Session Context Request: %+v", ascReqData)
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logging the full App Session Context request with %+v at INFO level can leak sensitive UE/session identifiers and can be very verbose in production. Consider lowering this to DEBUG and/or logging only key fields (e.g., Supi/IPs/DNN/MedComp count) after redaction.

Suggested change
logger.PolicyAuthorizationlog.Infof("Received App Session Context Request: %+v", ascReqData)
// Log only key, partially redacted fields to avoid leaking full session context details
supi := ascReqData.Supi
if len(supi) > 5 {
supi = supi[:5] + "..."
}
medCompCount := 0
if ascReqData.MedComponents != nil {
medCompCount = len(ascReqData.MedComponents)
}
logger.PolicyAuthorizationlog.Infof(
"Received App Session Context Request: Supi=%s UeIpv4=%s UeIpv6=%s Dnn=%s MedCompCount=%d",
supi, ascReqData.UeIpv4, ascReqData.UeIpv6, ascReqData.Dnn, medCompCount,
)

Copilot uses AI. Check for mistakes.
smPolicy.PackFiltIdGenarator++
}
pccRule.FlowInfos = flowInfos
tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, "", medSubComps[0].FStatus)
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medSubComps[0] is accessed to get FStatus when creating tcData, but medSubComps can be an empty slice (e.g., request contains an empty MedSubComps map). This will panic. Add an explicit length check and return a ProblemDetails error (or derive flow status from medComp / default) when no sub-components are provided.

Suggested change
tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, "", medSubComps[0].FStatus)
// Derive flow status for TcData; avoid panicking on empty medSubComps slice.
var fStatus models.FlowStatus
if len(medSubComps) > 0 {
fStatus = medSubComps[0].FStatus
} else {
// Fall back to a sensible default when no media sub-components are provided.
fStatus = models.FlowStatus_ENABLED
}
tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, "", fStatus)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants