Skip to content

UPF: Add minimal Nupf_EventExposure (EES) with USER_DATA_USAGE_MEASURES; refactor aligned to v1.2.7#79

Open
haha39 wants to merge 9 commits into
free5gc:mainfrom
haha39:feat/embedded-ees
Open

UPF: Add minimal Nupf_EventExposure (EES) with USER_DATA_USAGE_MEASURES; refactor aligned to v1.2.7#79
haha39 wants to merge 9 commits into
free5gc:mainfrom
haha39:feat/embedded-ees

Conversation

@haha39

@haha39 haha39 commented Oct 15, 2025

Copy link
Copy Markdown

Summary

This PR embeds a minimal Event Exposure (demo) pipeline into go-upf:

  • PFCP USAR -> in-proc Index (keyed by (SEID, URR), monotonic URSEQN)
  • Subscription API: POST/DELETE /nupf-ee/v1/ee-subscriptions
  • Reporter: provider-clock slot-aligned periodic aggregation (period whitelist)
  • Notifier: HTTP POST JSON to subscriber callback
  • Config via UPF-EES.yaml ees: block (api.listen, reporter.whitelist/slot, index.ttl, notifier.timeout/retries)

This is a non-3GPP SBA extension for demo/research. PFCP side stays compliant to TS 29.244 Usage Reporting (URR/USAR).

Motivation

  • Enables lab/demo for USER_DATA_USAGE_MEASURES-like notifications without adding an external sidecar.
  • Provides a clean reference for provider-clock scheduling and on-demand snapshots.

Design Notes

  • Provider-clock alignment (e.g., 10s boundaries) with a period whitelist (10/30/60s).
  • Immediate snapshot on creation (optional). On-demand = immediate=true + maxReports=1.
  • In-memory only (no persistence). Index TTL & ring size are configurable.

Docs

  • README.md

Compatibility

  • PFCP behavior unchanged for SMF.
  • EES is disabled by default if ees.enabled: false.

Follow-ups (if maintainers are interested)

  • Optional “3GPP-like” payload schema and OAuth2/HTTP2 per TS 29.500/29.501.
  • NRF registration (declared as experimental NF) or moving exposure to SMF/PCF.

@haha39 haha39 marked this pull request as draft October 23, 2025 13:36
@haha39

haha39 commented Oct 23, 2025

Copy link
Copy Markdown
Author

Converting to draft while I’m doing a larger refactor. I’ll ping when it’s ready for review.

@haha39 haha39 force-pushed the feat/embedded-ees branch from 1c13536 to 88ae730 Compare October 29, 2025 14:45
@haha39 haha39 changed the title feat(ees): embedded UPF Event Exposure (demo) — PFCP usage -> in-proc index -> HTTP notifications UPF: Add minimal Nupf_EventExposure (EES) with USER_DATA_USAGE_MEASURES; refactor aligned to v1.2.7 Oct 29, 2025
@haha39 haha39 marked this pull request as ready for review October 29, 2025 15:11
@haha39

haha39 commented Oct 29, 2025

Copy link
Copy Markdown
Author

This PR introduces a minimal, standards-aligned Event Exposure Service (EES) for UPF focusing on USER_DATA_USAGE_MEASURES over Nupf_EventExposure.

Highlights

  • Interval semantics with StartTime / EndTime (no cumulative counters on EES path)
  • Modes: PERIODIC (configurable PeriodSec) and ON_DEMAND (immediate once, then periodic)
  • Target: Any UE (all active PDU sessions)
  • Notify payload: per-session UL/DL bytes & packets (+ optional throughputs)
  • Minimal REST: POST /nupf-ee/v1/ee-subscriptions, DELETE /nupf-ee/v1/ee-subscriptions/{id}

Refactor (aligned to v1.2.7)

  • New internal/ees/* module (types, subscription_store, notifier, source_pfcp, aggregator, api)
  • Mirror PFCP USAReport interval data into EES (single source of truth)
  • Config: EES.Enabled, EES.ListenAddr, EES.PeriodSec, EES.LogLevel

Notes

  • Keeps PFCP behavior unchanged; EES only mirrors already-computed interval stats
  • Logs include subscription/session identifiers for easier troubleshooting

Thanks to the maintainers for the review and guidance!!

@Alonza0314 Alonza0314 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi, sorry for the late reply.
We’ve taken an initial look at this PR. It appears to introduce a new feature—thank you for your contribution and for taking the time to work on this.
That said, some parts of the changes don’t seem to align well with our current architecture. In particular, there are YAML files that look tailored to a specific experimental setup, as well as a README that differs significantly from the existing project style.
Could you please take another look and clarify your design choices? This would help us better understand the intent and proceed with the review more smoothly. Thank you!

@hokusai0603

Copy link
Copy Markdown

Hi @Alonza0314,
I apologize for the late reply. We are currently working on the requested changes and will provide an update soon.

Thank you!

hokusai0603

@hokusai0603

Copy link
Copy Markdown

Technical Submission: Nupf_EventExposure Service for go-upf

This document provides a comprehensive technical overview and Pull Request documentation for the Event Exposure Service (EES) implementation in go-upf. It integrates architectural designs, data flow specifications, and 3GPP compliance details.

1. Introduction

This PR adds a UPF-side implementation of the Nupf_EventExposure service as defined in 3GPP TS 29.564 Release 17/19. The service allows NF consumers (e.g., NWDAF, SMF, PCF) to subscribe to real-time and immediate user plane event reports, specifically focusing on data usage metrics.

Key Implementation Paths:

  • internal/ees/: Core EES logic (REST API, Aggregation, Notification delivery).
  • internal/pfcp/: Session context management and metadata extraction.
  • pkg/app/: System integration and report dispatching.

2. Software Architecture

The EES is designed as an independent plane within the UPF, adhering to the Control and User Plane Separation (CUPS) architecture. It operates as a secondary consumer of usage reports dispatched from the data plane.

2.1 Component Mapping

Component Logical Function Implementation Path
EES API Server Manages subscriptions via RESTful interface. internal/ees/api.go
Dispatcher Multicasts reports from Forwarder to PFCP and EES. pkg/app/dispatcher.go
EES Aggregator Buffers and consolidates reports per subscription. internal/ees/aggregator.go
EES Notifier Delivers 3GPP-compliant JSON notifications. internal/ees/notifier.go
PFCP Server Extracts UE IP/SEID metadata for EES matching. internal/pfcp/node.go

2.2 System Initialization Chain

---
config:
  layout: elk
---
graph TD
    Main[main.go] -->|calls| Run[app.go: UpfApp.Run]

    subgraph "Forwarding Plane Setup"
        Run --> NewDriver[forwarder.NewDriver]
        NewDriver --> Gtp5g[gtp5g.go: NewGtp5g]
    end

    subgraph "Control Plane Setup"
        Run --> NewPFCP[pfcp.NewPfcpServer]
        Run --> NewDisp[app/dispatcher.go: NewDispatcher]
        Run --> HandRep[driver.HandleReport]
        Run --> StartPFCP[pfcp.go: PfcpServer.Start]
    end

    subgraph "Event Exposure Setup (initEES)"
        Run --> InitEES[app.go: UpfApp.initEES]
        InitEES --> NewStore[ees/subscription_store.go: NewSubscriptionStore]
        InitEES --> NewNotif[ees/notifier.go: NewNotifier]
        InitEES --> NewAgg[ees/aggregator.go: NewAggregator]
        InitEES --> NewHdlr[ees/handler.go: NewHandler]
        InitEES --> RegEES[dispatcher.go: RegisterEESHandler]

        InitEES -->|goroutine| RunAgg[ees/aggregator.go: Aggregator.Run]
        InitEES -->|goroutine| ServeAPI[ees/api.go: Server.Serve]
    end

    %% Highlight New/Modified Components
    classDef eesNew fill:#f96,stroke:#333,stroke-width:2px;
    class InitEES,NewDisp,RegEES,NewStore,NewNotif,NewAgg,NewHdlr,RunAgg,ServeAPI eesNew;

    style Run fill:#dfd,stroke:#333
Loading

3. Data Processing Flow: Life of a Usage Report

The EES utilizes a Pure Push Model, leveraging existing SMF-provisioned URRs (specifically URRID 2 - Measurement After QoS Enforcement) to capture telemetry without redundant kernel overhead.

sequenceDiagram
    participant K as gtp5g (Kernel)
    participant F as Forwarder (Gtp5g Driver)
    participant P as PFCP Server

    box "Event Exposure Module (New)"
        participant D as Dispatcher
        participant H as EES Handler
        participant A as EES Aggregator
        participant N as EES Notifier
    end

    participant C as Consumer (e.g. NWDAF)

    Note over K, F: 1. Periodic/Threshold Trigger
    K->>F: Push Usage Report (URR 2)
    F->>D: NotifySessReport(sessRpt)

    par Multicast by Dispatcher
        D->>P: NotifySessReport (to SMF via N4)
    and
        D->>H: NotifySessReport
    end

    H->>A: PushReport (Consolidate immediately)

    Note over A: 2. Subscription Period Elapsed
    A->>N: Notify(subscription, measures)
    N->>C: HTTP POST (TS 29.564 Payload)
    C-->>N: 200 OK / 204 No Content
Loading

4. 3GPP Compliance Status (TS 29.564)

Feature Status Implementation Detail
USER_DATA_USAGE_MEASURES ✅ Full Volume (Bytes/Packets) and Throughput (bps/pps).
PERIODIC Trigger ✅ Full Respects reportPeriod. Ticker aligns with URR cycles.
ONE_TIME Trigger ✅ Full Immediate Report: Sends zero-value reports if buffer is empty, then implicitly deletes subscription.
PER_SESSION Granularity ✅ Full Aggregated based on UE IPv4 address.
anyUe Targeting ✅ Full Monitors all active sessions within the UPF.
ueIpAddress Targeting ✅ Full Targets specific sessions via IPv4 matching.

5. External API

Base URI: {upf_ip}:8088/nupf-ee/v1

Method Endpoint Description
POST /ee-subscriptions Create a new event subscription
DELETE /ee-subscriptions/{id} Terminate an existing subscription

Notification Payload (JSON):
The EES Notifier delivers standardized payloads containing notificationItems, each including eventType, timeStamp, ueIpv4Addr, and the specific userDataUsageMeasurements (Volume and Throughput).


6. Design Decisions & Engineering Excellence

6.1 Performance & Overhead

  • Zero-Redundancy: By reusing standard URRID 2, the implementation avoids programming redundant "Shadow URRs," reducing Netlink traffic and kernel state by approximately 50%.
  • Dynamic Period Alignment: The Aggregator automatically tunes its internal ticker to be a multiple of the kernel's URR reporting period, minimizing data lag.

6.2 Reliability & Compliance

  • Zero-Value Immediate Reporting: To satisfy the "Immediate" requirement for ONE_TIME triggers, the system generates a 0-value report if no traffic has been pushed yet, ensuring the consumer is not left hanging.
  • Implicit Deletion: Implements the 3GPP lifecycle rule where ONE_TIME subscriptions are automatically purged after the first successful notification.
  • Thread Safety: Uses sync.RWMutex for session lookups, allowing the EES to query SEID-to-IP mappings without blocking core PFCP signaling.

6.3 Inter-Component Dependencies (SMF Integration)

To fully support Volume Threshold reporting through the Event Exposure Service, a modification in the SMF (smf/internal/context/pfcp_rules.go) is required to ensure the correct PFCP Reporting Triggers are provisioned:

// Required change in SMF for Volume Threshold provisioning
func NewVolumeThreshold(threshold uint64) UrrOpt {
    return func(urr *URR) {
        if threshold > 0 { 
            urr.ReportingTrigger.Volth = true
            urr.VolumeThreshold = threshold
        }
    }
}

This is to address the issue mentioned in free5gc/smf#223, ensuring that URRs report precise volume flow counts periodically, instead of only providing reports when a volume threshold is breached.


7. Usage & Testing

7.1 Configuration

Enable the service in config/upfcfg.yaml:

ees:
  enabled: true
  listenAddr: "0.0.0.0:8088"
  periodSec: 10

7.2 Unit Testing

A comprehensive test suite is included, utilizing gock for HTTP mocking:

# Run all EES tests, including API, Notifier, and On-Demand Lifecycle
go test -v ./internal/ees/...

Key Tests:

  • api_test.go: Validates REST constraints and granularity checks.
  • notifier_test.go: Verifies 3GPP JSON schema and HTTP error handling.
  • ondemand_test.go: Confirms the ONE_TIME reporting and deletion logic.

Standards References:

  • 3GPP TS 29.564: 5G System; User Plane Function Services; Stage 3.
  • 3GPP TS 29.244: PFCP Interface Specification.

@hokusai0603

Copy link
Copy Markdown

Hello @Alonza0314 ,

I recently re-ran all the tests and updated the design documents in this pr, would you please take another look at this pr again?

Thank you,
@hokusai0603

@hokusai0603

Copy link
Copy Markdown

Updated, could you please take another look again?

@Alonza0314

Copy link
Copy Markdown
Member

Hi guys, we plan to merge this feature after the release this month. In other words, this feature will be merge at next release, maybe in July or in August. This will be reviewed with another ee PR.

Please also check that if it is necessary to modify the config file at free5GC's main repo or not.

@d11nn @roundspring2003 FYI!

@d11nn

d11nn commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

@Alonza0314 Got it.
Hi @haha39 , plz fix CI issues, thanks!

@hokusai0603

Copy link
Copy Markdown

@d11nn Noted, will work on it right away !

@d11nn

d11nn commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Hi @hokusai0603,

Please fix CI issues again~
You can use golangci-lint(1.26.2) to test linter on your local environment first also.

BR,
Daniel

@hokusai0603

Copy link
Copy Markdown

Hi @d11nn ,

I have updated the corresponding configs in the main repo and pushed the final changes to align the config styles further. Please take a final look at this pr alongside the main repo's pr.

Best regards,
hokusai0603

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.

4 participants