OmniPCF Operations Guide
Overview
OmniPCF implements the Policy Control Function (PCF) of the 5G Core. It provides two SBI services: Npcf_SMPolicyControl (TS 29.512) for session management policy associations, and Npcf_AMPolicyControl (TS 29.507) for access and mobility policy associations. The PCF optionally queries the UDR for per-subscriber policy data (subscription QoS, UE-AMBR) and builds Policy and Charging Control (PCC) decisions which are returned to the SMF and AMF respectively.
Policy context is held in-process. All PCC rules generated are permit-all default rules; dynamic, subscriber-specific, or GBR flow rules are not supported in the current release.
Architecture
3GPP Role and Specification References
| Specification | Relevance |
|---|---|
| TS 23.501 | System architecture — PCF role, PCC framework |
| TS 23.503 | Policy and charging control architecture |
| TS 29.507 | Npcf_AMPolicyControl API |
| TS 29.512 | Npcf_SMPolicyControl API |
| TS 29.519 | Nudr_DataRepository — policy data resource (queried by PCF) |
| TS 23.502 | Procedures — references to policy association creation during PDU session establishment and registration |
SBI Endpoints
All endpoints are served under the base URL {sbi_scheme}://{sbi_addr}:{sbi_port}.
| Method | Path | Service | Description | Spec |
|---|---|---|---|---|
| POST | /npcf-smpolicycontrol/v1/sm-policies | Npcf_SMPolicyControl | Create SM Policy Association | TS 29.512 4.2.2.2 |
| POST | /npcf-smpolicycontrol/v1/sm-policies/{smPolicyId}/update | Npcf_SMPolicyControl | Update SM Policy Association | TS 29.512 4.2.3.2 |
| POST | /npcf-smpolicycontrol/v1/sm-policies/{smPolicyId}/delete | Npcf_SMPolicyControl | Delete SM Policy Association | TS 29.512 4.2.4.2 |
| POST | /npcf-am-policy-control/v1/policies | Npcf_AMPolicyControl | Create AM Policy Association | TS 29.507 4.2.2.2 |
| DELETE | /npcf-am-policy-control/v1/policies/{polAssoId} | Npcf_AMPolicyControl | Delete AM Policy Association | TS 29.507 4.2.4.2 |
Request / Response Summary
Create SM Policy Association — mandatory request fields: supi, pduSessionId, pduSessionType, dnn, notificationUri, sliceInfo, and at least one of ipv4Address or ipv6AddressPrefix. Returns 201 Created with SmPolicyDecision and Location header.
Update SM Policy Association — the SMF sends SmPolicyUpdateContextData. The PCF updates the stored context with any provided ipv4Address, ipv6AddressPrefix, or ratType fields and returns a refreshed SmPolicyDecision. Rule report processing is not performed (see PCF-M3).
Delete SM Policy Association — body is SmPolicyDeleteData (ignored beyond logging). Returns 204 No Content.
Create AM Policy Association — mandatory request fields: supi, notificationUri. Optional fields include guami, accessType, ratType, allowedSnssais, ueAmbr, suppFeat. Returns 201 Created with PolicyAssociation and Location header.
Delete AM Policy Association — no request body required. Returns 204 No Content.
Configuration Reference
Configuration is read from the application environment key :omnipcf.
config :omnipcf,
sbi_scheme: "http",
sbi_addr: "127.0.0.13",
sbi_port: 7777,
nrf_uri: "http://127.0.0.10:7777",
udr_uri: "http://127.0.0.12:7777",
mcc: "999",
mnc: "70",
heartbeat_interval: 10_000
Parameter Table
| Parameter | Type | Default | Description |
|---|---|---|---|
sbi_scheme | string | "http" | HTTP scheme for the SBI listening socket (http or https) |
sbi_addr | string | "127.0.0.13" | IP address the SBI HTTP server binds to |
sbi_port | integer | 7777 | TCP port the SBI HTTP server listens on |
nrf_uri | string | "http://127.0.0.10:7777" | Base URI of the NRF. Used for NF registration and heartbeat only |
udr_uri | string | "http://127.0.0.12:7777" | Base URI of the UDR. Queried for AM policy data (/nudr-dr/v1/policy-data/ues/{ueId}/am-data) and SM policy data (/nudr-dr/v1/policy-data/ues/{ueId}/sm-data). If unavailable, the PCF proceeds with default policy |
mcc | string | "999" | Mobile Country Code of the serving PLMN |
mnc | string | "70" | Mobile Network Code of the serving PLMN |
heartbeat_interval | integer (ms) | 10000 | Interval in milliseconds between NRF heartbeat requests |
hss_api_base_url | string | "https://127.0.0.1:8443" | Base URL of a legacy HSS API. Present in configuration but not used by active policy procedures |
Key Procedures
SM Policy Association Creation (TS 29.512 Section 4.2.2)
SM Policy Association Update (TS 29.512 Section 4.2.3)
Note: Rule reports within SmPolicyUpdateContextData are not processed (PCF-M3). Trigger-based policy updates on the SMF's own update requests are not performed (PCF-M4). Proactive notification of the SMF is performed for AF-triggered changes — see Policy Authorization for AF Sessions below.
Policy Authorization for AF Sessions (Npcf_PolicyAuthorization)
This is the PCF side of the VoNR dynamic dedicated bearer. The P-CSCF (acting as an AF) creates an application session when a call is answered and deletes it on BYE; the PCF turns that into a GBR PCC rule and pushes it to the SMF that owns the UE's SM policy.
Matching the AF session to the right SM policy is done by UE IPv4 against the live SM-policy worker registry (PolicySupervisor.sm_workers_by_ue_ipv4/1), not a static context map. To keep one UE IP mapped to exactly one live association, SmPolicyWorker.create/1 calls supersede_sm_by_ue_ipv4/1 first, so a stale worker with a reused IP can't shadow the current session (supersede-on-create). The SMF-facing notification URI is the one the SMF advertised at policy creation: {smf}/nsmf-callback/sm-policy-notify/{smContextRef}.
AM Policy Association Creation (TS 29.507 Section 4.2.2)
SmPolicyDecision Structure
The PCF always returns a default permit-all decision. The structure returned per TS 29.512 Table 5.6.2.3-1:
SmPolicyDecision
sessRules:
SessRule-{dnn}:
sessRuleId: "SessRule-{dnn}"
authSessAmbr: {uplink, downlink} <- from UDR or default 1000 Kbps
authDefQos: {5qi: 9, arp: {...}} <- from UDR or 5QI=9 ARP-priority=8
pccRules:
PccRule-{dnn}-default:
pccRuleId: "PccRule-{dnn}-default"
precedence: 255
flowInfos: [permit out ip from any to {ueIp},
permit out ip from {ueIp} to any]
refQosData: ["QosData-{dnn}"]
refTcData: ["TcData-{dnn}"]
qosDecs:
QosData-{dnn}:
5qi: 9
arp: {priorityLevel: 8, preemptCap: NOT_PREEMPT, preemptVuln: PREEMPTABLE}
maxbrUl / maxbrDl: session AMBR values
traffContDecs:
TcData-{dnn}:
flowStatus: ENABLED
suppFeat: echoed from request (see PCF-M6)
Prometheus Metrics
SM Policy Metrics
| Metric | Type | Tags | Description |
|---|---|---|---|
omni_pcf.sm_policy.create.count | counter | supi, dnn, result | SM policy create operations |
omni_pcf.sm_policy.delete.count | counter | supi, dnn | SM policy delete operations |
omni_pcf.sm_policy_creates.total | counter | result | Total SM policy creates |
omni_pcf.active_sm_policies.count | gauge | -- | Number of active SM policies |
AM Policy Metrics
| Metric | Type | Tags | Description |
|---|---|---|---|
omni_pcf.am_policy.create.count | counter | supi, result | AM policy create operations |
omni_pcf.am_policy.delete.count | counter | supi | AM policy delete operations |
omni_pcf.am_policy_creates.total | counter | result | Total AM policy creates |
omni_pcf.active_am_policies.count | gauge | -- | Number of active AM policies |
PCC Rule Metrics
| Metric | Type | Tags | Description |
|---|---|---|---|
omni_pcf.pcc_rule_installs.total | counter | -- | Total PCC rule installations |
NRF Metrics
| Metric | Type | Tags | Description |
|---|---|---|---|
omni_pcf.nrf.registration.status | gauge | nf_type | NRF registration status (1=registered, 0=not) |
BEAM VM Metrics
| Metric | Type | Description |
|---|---|---|
beam.memory.total | gauge | Total BEAM memory in bytes |
beam.memory.processes | gauge | Memory used by Erlang processes |
beam.memory.processes_used | gauge | Memory actually used by processes |
beam.memory.system | gauge | System memory |
beam.memory.atom | gauge | Total atom memory |
beam.memory.atom_used | gauge | Used atom memory |
beam.memory.binary | gauge | Binary memory |
beam.memory.code | gauge | Code memory |
beam.memory.ets | gauge | ETS table memory |
beam.processes.count | gauge | Number of Erlang processes |
beam.ports.count | gauge | Number of Erlang ports |
beam.atom.count | gauge | Number of atoms |
beam.vm.uptime | gauge | VM uptime in seconds |
Known Limitations
| ID | Area | Description |
|---|---|---|
| PCF-M1 | AM Policy Update | There is no POST /npcf-am-policy-control/v1/policies/{polAssoId}/update endpoint. The AMF cannot request policy updates for an existing AM policy association. Only create and delete are supported. |
| PCF-M2 | AM Policy Notification | The PCF does not send policy update notifications to the AMF callback URI. AMF-side policy changes (e.g., UE-AMBR modification) are never pushed by the PCF. |
| PCF-M3 | Rule Report Processing | RuleReport entries within SmPolicyUpdateContextData are not inspected or processed. The PCF cannot react to rule enforcement failures or changes reported by the SMF. |
| PCF-M4 | Trigger-based Updates | PolicyControlRequestTrigger values are not evaluated. The PCF does not detect or respond to events such as PLMN change, RAT change, or access type change that would normally trigger a policy update. |
| PCF-M5 | Dynamic PCC Rules | Only a single default permit-all PCC rule is generated per session. No service-data-flow-specific PCC rules, application detection rules, or subscriber-specific policy from UDR are applied. |
| PCF-M6 | Feature Negotiation | suppFeat in SM and AM policy responses is set to the value echoed from the request rather than computed as a bitwise AND of the PCF's supported features and the consumer's requested features (TS 29.512 Section 6.1). |
| PCF-M7 | SM Policy Notification | The PCF does not invoke the SMF's notificationUri to push policy decisions or updates. All PCF-initiated SM policy updates (e.g., in response to application function requests) are absent. |
| PCF-L1 | GBR Flows | Guaranteed Bitrate (GBR) QoS flows are not supported. The QER and PCC rules only express MBR-based constraints. |
| PCF-L3 | UDR Policy Subscription | The PCF queries the UDR once at policy association creation. There is no subscription to UDR data change notifications (Nudr_DataRepository_Subscribe), so changes to subscriber policy data in the UDR are not reflected in active policy associations. |
| CROSS-2 | UDR Endpoint Mismatch | The PCF queries /nudr-dr/v1/policy-data/ues/{ueId}/am-data and .../sm-data on the UDR. These endpoints are not exposed by OmniUDM in the current release. UDR queries will return 404 and the PCF will silently fall back to default policy. |
Troubleshooting
SM Policy Association Returns 400 ERROR_INITIAL_PARAMETERS
The SmPolicyContextData from the SMF is missing a mandatory field. The PCF requires: supi, pduSessionId, pduSessionType, dnn, notificationUri, sliceInfo, and at least one of ipv4Address or ipv6AddressPrefix. Check that the SMF is sending the UE IP address in the create_sm_policy call — the SMF populates ipv4Address from the context's ue_ipv4 field, which is set by the PFCP handler after session establishment. If PFCP fails before IP allocation, the field will be absent.
SM Policy Association Returns 403 POLICY_CONTEXT_DENIED
Returned only when a specific denial is encountered in policy validation (not currently triggered by default policy logic). If seen unexpectedly, check the PCF log for [SM Policy] Created association ... failed entries.
UDR Queries Always Fail
See limitation CROSS-2. OmniUDM does not expose the /policy-data/ resource tree. The PCF logs a warning [UDR Client] SM policy query failed for {supi} and proceeds with default policy. This is expected in the current deployment. No corrective action is needed unless a UDR that exposes TS 29.519 policy data resources is deployed.
Policy Decision Contains Default AMBR Instead of Subscribed Values
This occurs when the UDR query fails (CROSS-2) or the UDR returns an empty body. The default session AMBR applied is 1000 Kbps uplink and downlink. To override, ensure the UDR returns sessionAmbr in the SM policy data response, or configure subscriber data in a UDR that implements the TS 29.519 policy data resource.
Feature Negotiation Mismatch with SMF
Due to PCF-M6, the suppFeat in the SM policy response echoes the value from the SMF request rather than performing a proper bitwise AND. If the SMF or AMF relies on specific feature bits being masked off, unexpected behavior may result. As a workaround, configure the SMF to send only the features it actually needs in suppFeat.
AM Policy Associations Accumulate Without Bound
AM policy associations are created at UE registration and deleted at deregistration. If the AMF does not send the DELETE when deregistering (e.g., due to AMF restart), associations will persist indefinitely. There is no expiry mechanism. Monitor the /statistics endpoint for association count. To manually clear stale associations, restart OmniPCF (all state is in-process and non-persistent).
Log Correlation
SM policy log lines are prefixed [SM Policy] and include the association ID and SUPI. AM policy log lines are prefixed [AM Policy]. UDR client calls are prefixed [UDR Client]. All entries include the SUPI, enabling per-subscriber tracing across the PCF log.