Repository navigation
fix: preserve QoS flow marking and charging across TI and ULCL updates - #253
Conversation
|
Fixed the stale flow-QER profile issue in commit 10af0d2.
Regression tests exercise QoS-data-only updates for the same QoS ID/QFI and encode/parse PFCP Session Modification requests. They cover MBR increases/decreases/addition/removal, GBR changes/addition/removal, unchanged equivalent rates, shared PCC/static ULCL references, and old-QER cleanup. Additional normal/DC activation tests cover changed and invalid rate data. Local validation passed: |
|
Addresses the PR review's P2: Static ULCL rebuilds every active static PDR after each PCC update in commit 6b16b6c. Static refresh now compiles normalized desired classifier/QoS/charging rules and reconciles them against existing PDRs using a classifier index. Unchanged rules retain their PDR objects and IDs, QER/URR references, and runtime quota; only changed or removed classifiers enter the replacement/retirement flow. Comparisons include effective filters, precedence, QFI, gate/MBR/GBR, Session-AMBR attachment, and charging identity. Filter reordering and equivalent bitrate units do not force replacement. The plan is rebuilt from current policy rather than relying on a persisted fingerprint cache. The same planning/application code serves path activation and static refresh. Session-level charging references are collected once per path, avoiding the repeated PCC scans found during benchmarking. Existing PFCP sessions with no pending operations skip modification requests and response waiting; affected UPFs still receive their updates, including URR quota updates and queries. Regression coverage includes repeated/empty/unrelated notifications, partial QoS and charging changes, reordered filters, direction-specific removal, preservation of live URR quota/refcounts, and suppression of empty N4 requests. Local full tests/build, targeted race tests, and lint passed. For 64 classifiers, the local unchanged-policy benchmark improved from about 37.1 ms/op to 2.0 ms/op and 70.7 MB/op to 3.4 MB/op (median of three runs against 10af0d2 with the same fixture). This measures policy application and local cleanup, excluding network latency and real UPF/UE execution. Full free5gc/ci-test has not been run for this revision. |
A dedicated non-GBR QoS Flow's PDR can reference both the shared Session-AMBR QER and its own flow QER. When the shared QER carries the default QFI (for example 1) and the flow QER carries QFI 4, the same matching traffic receives conflicting packet-marking instructions. Removing QFI from the shared QER also exposes paths that previously relied on that QER for marking: static ULCL/MEC paths need an explicit flow QER and must preserve the QoS and charging policy of the traffic they carry.
This PR separates Session-AMBR enforcement from QoS flow marking and applies explicit QoS bindings during normal, DC and static ULCL path activation. A static MEC route can carry both default and dedicated flows; selecting that route does not itself select the default QoS Flow.
Changes
DefQosQFIfor default bindings, includingDefQosFlowIndication, without creating another default flow or treating the indication as a new QoS profile. Dedicated flows retain their referenced QoS data; non-GBR flow MBR remains optional.Code layout
The implementation and regressions are grouped by responsibility, with seven new files in total (two implementation files and five test files):
internal/context/path_qos.go: common QoS planning/reconciliation, directional SDF handling and classifier cleanup.internal/context/ulcl_qos.go: static route/PCC intersections, charging bindings and static refresh.internal/context/pfcp_rules.go; PFCP rule collection and pending-operation checks reside ininternal/sbi/processor/datapath.go.datapath_qos_test.go,ulcl_qos_test.goandtraffic_influence_policy_test.go. Processor regressions are grouped intodatapath_internal_test.goandcharging_trigger_internal_test.go. Shared-QER retirement encoding tests are included in the existingbuild_modification_test.go.The file consolidation moves declarations and import aliases only; behavior and all existing test/benchmark cases are retained.
Standards rationale
The conclusion that QFI 1 and QFI 4 on QERs referenced by the same dedicated-flow PDR create a semantic conflict is an interpretation of these requirements. This PR does not claim a blanket prohibition on QFI in every AMBR QER or a particular UPF outcome. The cited provisions do not supply a first-QER-wins or ignore-the-default-QFI resolution rule. The static-route intersection and precedence allocation are implementation choices for retaining the existing policy, not algorithms prescribed by these clauses.
Validation and scope
Passed locally:
go test ./...go build ./...go test -race ./internal/context ./internal/sbi/processor ./internal/pfcp/messagegolangci-lint run ./...— 0 issuesgit diff --checkRegression coverage includes optional QFI wire encoding, NGAP confirmation, normal/DC activation, TI policy changes, static full/partial PCC overlap, default fallback, direction/protocol/ports, explicit TI routing priority, PCC add/delete refresh, GBR and charging references, shared-rule retirement, final usage and late quota responses, and UPF charging identity. Mock PFCP tests encode and parse requests across the static ULCL phases, including downlink-only rule definitions. Additional wire regressions exercise QoS-data-only updates for the same QoS ID/QFI: MBR increases/decreases/addition/removal, GBR changes/addition/removal, equivalent rate units, shared PCC/static references, replacement rule IDs, and final cleanup. Normal and DC activation also cover changed and invalid rate data. Incremental regressions verify stable static PDR IDs on no-op/unrelated notifications, partial QoS and charging replacement, filter reordering, removal of only the affected direction, preservation of live URR quota/refcounts, and suppression of empty N4 modifications while URR updates/queries still reach the affected UPF.
Local control-plane benchmark
go test ./internal/context -run '^$' -bench '^BenchmarkStaticULCLNoopPolicyUpdate$' -benchmem -benchtime=200ms -count=3Compared with
10af0d2using the same benchmark fixture in an isolated copy. Median of three runs on the same machine; the workload includesApplyPccRules()and local retirement cleanup for an unchanged policy. It excludes PFCP network latency and real UPF/UE execution. The current benchmark also checks that static PDR objects remain unchanged.Local
free5gc/ci-testULCL execution with real UPFs/UE passed 14/14 routing, policy and charging-usage cases (eight TI sessions and six static multipath sessions) using local PCF/SMF binaries. Session-URR regressions additionally encode and parse PFCP Modification requests and verify reference counts during service/default path removal and recreation. These e2e assertions do not establish wire QFI/MBR enforcement or successful final account settlement: CHF requestedUnit validation and the SMF/PCF account-deletion order are separate charging issues outside this PR. A separately patched local CHF accepts the valid final online reports; the account-deletion ordering issue remains. Static intersection supports the implemented IP flow-filter subset; AppId/Ethernet classification, unsupported filter syntax, missing QoS data, or insufficient PDR precedence space return errors. This change does not add a complete PFCP failure rollback mechanism.The branch includes official main at
572d3bd; the deleted legacyinternal/pfcp/message/build.gois not restored. Related PCF policy changes: free5gc/pcf#87.