Conversation
|
The producing end is webconsole#565, which adds |
11cd358 to
35626b9
Compare
|
Pushed
So the lookup is now checked and an unmapped media type keeps the documented default of 9, which leaves no behaviour difference for any input the enum can produce. Gates re-run on the pushed tree: |
|
Follow-up opened as #391, stacked on this one: it warns when a policy configures a guaranteed rate against a standardised Non-GBR 5QI, which this PR's table makes checkable. It is the item this PR's description listed as deliberately not included, so it is separate rather than folded in here. One thing from it is worth knowing here: it reads the Non-GBR block of TS 23.501 table 5.7.4-1 and that block includes 5QI 10, added for satellite access with an 1100 ms packet delay budget. |
35626b9 to
6ee5043
Compare
There was a problem hiding this comment.
🟡 Changes recommended
context/ue.go still contains an IncreaseRemainGBR path that uses the old GetVar5qi() <= 4 check, which will keep GBR budgets inconsistent for standardised GBR 5QIs above 4.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR improves QoS/GBR handling in the PCF by (1) propagating guaranteed bit rates from slice PCC QoS configuration into generated QosData, and (2) replacing the incorrect 5QI <= 4 GBR classification with a standards-aligned helper (context.IsStandardisedGbr5QI) across policy authorization and UE GBR budgeting paths.
Changes:
- Extend
makeQosDescto carryGbrUl/GbrDlfrom slice policy intomodels.QosData. - Replace
5QI <= 4GBR detection withIsStandardisedGbr5QIin policy authorization and UE remaining-GBR decrease logic. - Add targeted tests validating GBR classification (including 5QI 66) and guaranteed-rate propagation.
File summaries
| File | Description |
|---|---|
| util/pcc_rule_test.go | Adds coverage to ensure MediaTypeTo5qiMap is total over the MediaType enum and never yields 5QI=0. |
| producer/policyauthorization.go | Uses checked media-type→5QI lookup and standards-based GBR classification for QoS/rate updates. |
| producer/policyauthorization_test.go | Adds a regression test ensuring GBR 5QI>4 (e.g., 66) gets guaranteed rates authorized into stored QoS data. |
| polling/pcc_policy_config.go | Propagates configured guaranteed bit rates (GbrUl/GbrDl) into generated QosData. |
| polling/pcc_policy_config_test.go | Adds tests verifying guaranteed bit rates are carried when configured and remain unset otherwise. |
| context/ue.go | Switches remaining-GBR decrease budgeting to standards-based GBR detection. |
| context/gbr.go | Introduces IsStandardisedGbr5QI helper based on TS 23.501 table 5.7.4-1 sets. |
| context/gbr_test.go | Adds tests asserting the helper’s full standardised GBR/non-GBR behavior and budgeting effects. |
Review details
- Files reviewed: 8/8 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
6ee5043 to
6b4ffeb
Compare
6b4ffeb to
4b55d1e
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Two critical accounting issues remain unresolved: partial-debit rollback and slice-rule aggregate-credit handling.
Get a fresh assessment by requesting another Copilot review.
Review details
- Files reviewed: 8/8 changed files
- Comments generated: 2
- Review effort level: Lite
|
Both accounting findings are right, and both are reachable because of this PR rather than in spite of it. Fixed in Credit without a debit. The credit read the guaranteed rates off the stored The credit is now the mirror of a recorded debit, keyed by QoS data id, so a rule with no record is given back nothing. Tracing the takers is what made this more than a one-line change: Partial debit. Confirmed: the downlink is taken first, and on an uplink failure Two adjacent defects in the same accounting are still not fixed and are named in the description rather than folded in: Both fixes are mutation-verified — reverting the credit to read stored rates fails the slice-rule test, and removing the downlink restore fails the atomicity test. Two earlier tests moved onto the recorded debit, since they had encoded the invariant this change replaces. Gates on the pushed head: |
… properly Two changes that belong together, because the first is useless without the second. makeQosDesc built a QosData from the polled slice policy with the 5QI, ARP and maximum bit rates, dropping any guaranteed rate. It now carries GbrUl and GbrDl, so a slice policy can express a floor and not only a ceiling. That alone would not have been honoured, because the PCF decides whether a flow is GBR by Var5qi <= 4, in seven places. That is not the 3GPP definition. TS 23.501 table 5.7.4-1 gives a GBR resource type to 1 to 4, 65 to 67 and 71 to 76, with delay-critical GBR at 82 to 90, so 5QI 66 or 82 are silently mishandled today: a guaranteed rate the AF asks for is neither authorised on the QoS data nor budgeted against the UE's aggregate. IsStandardisedGbr5QI replaces the comparison with the table it should have been reading. Five of the seven are on the policy authorization path, where the 5QI is derived from the AF's media type and is therefore always a standardised value. Three of those five decide for a newly created PCC rule and two for an existing one — the same question either side of a found-or-create branch, so they have to move together, or an AF's second request for a rule is answered differently from its first. The remaining two are the aggregate budget's two directions, and they have to move together for the same reason. DecreaseRemainGBR debits a requested guaranteed rate against the UE's aggregate; IncreaseRemainGBR credits it back when RemovePccRule releases the rule. Moving only the debit would have left the credit reading <= 4, so a rate debited for a 5QI of 66 — which is precisely what this change starts doing — would never be given back, and the aggregate would shrink by that rate once per rule, permanently. Neither gate fires for such a 5QI today, so the pair is consistent before and after; it is splitting them that would introduce the leak. One behaviour change comes with that and is worth naming, because the old comparison hid it. `util.MediaTypeTo5qiMap` was read unchecked, so a media type outside the enum yielded a 5QI of 0, which `<= 4` accepted: an AF sending an unrecognised media type had its requested rates applied under a 5QI that TS 23.501 does not assign. Reading the table instead would have silently stopped applying them. So the lookup is now checked and an unmapped media type keeps the documented default of 9, which is what every valid media type already resolved to or better — the map is total over `models.AllowedMediaTypeEnumValues`, and a test pins that, since that totality is the only reason the default was unreachable for real input. The regression tests drive the call sites rather than the helper, so that what is under test is the decision and not the table lookup. DecreaseRemainGBR with a 5QI of 66 must return the requested rates and decrement the aggregate budget; RemovePccRule must credit that same rate back, and a debit followed by a release must leave the aggregate where it started; handleCombinedMediaSubComponents with a 5QI of 66 must authorise a guaranteed rate on the QoS data it stores; makeQosDesc must carry a configured guaranteed rate through, and must leave it unset when none is configured rather than defaulting it to the maximum. Each fails with the change reverted under it — empty rates, an untouched budget, a budget left short by the released rate, a dropped guarantee — which is the shape of the defect: unauthorised and unbudgeted rather than refused. Mirror cases pin that a standardised Non-GBR 5QI carrying rates is neither budgeted nor credited back, so neither direction can later be widened into treating everything as guaranteed. Budgeting is otherwise unchanged and stays consistent: DecreaseRamainBitRate treats an unset aggregate budget as no limit rather than as zero, so a deployment whose subscription data carries no aggregate GBR is simply not budgeted. Two pre-existing defects in that accounting are left alone here, because neither is this change's and each wants its own fix, but both widen slightly in reach and so are worth naming. Modifying a rule so that the new guaranteed rate exceeds the aggregate restores RemainGbrDL and RemainGbrUL from IncreaseRemainGBR's return values, which are nil whenever the previous rate was unset, and a nil budget reads downstream as no limit rather than as zero; the create arm has no rollback at all, so a request that passes on DL and fails on UL leaves DL debited. Both were unreachable for a 5QI above 4 before, since the old gate meant DecreaseRemainGBR could not fail for one. Separately, the two existing-rule arms on the authorization path debit an already-debited QoS without crediting it first, so an AF re-requesting a rule debits twice and only the last value is credited on release; that one is inert on this path, where the media type maps to a 5QI of 1, 2 or 9 only. Deliberately not included: a classifier for a dynamically assigned 5QI, which sits outside the table and carries its own QoS characteristics. Nothing in the PCF has to recognise one today. makeQosDesc copies the configured rates through without consulting the 5QI, so a slice policy that uses a dynamically assigned value still reaches the SMF carrying its guaranteed rate, and the SMF's CreateDedicatedQosQer keys off whether the rates are present rather than off the 5QI. Requires openapi v2.2.2 for nfConfigApi.PccQos.GbrUl and GbrDl. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Edvin Lindqvist <edvin.lindqvist@forsway.com>
… atomically Two accounting defects, both raised in review, both of which this PR's own change is what makes reachable. The credit read the guaranteed rates off the stored QoS data. That was sound while only an application function's request put them there, because modifyRemainBitRate writes back exactly what it managed to take. Carrying slice policy's guaranteed rates into QosData breaks the invariant: such a rule has rates but was never debited, and it still reaches RemovePccRule by the ordinary routes -- a delete operation, or an installation the SMF reports as failed. The budget would then be credited a rate nobody took, and rise above the aggregate the session started with. The credit is now the mirror of a recorded debit. Every path that takes from the budget records what it took against the QoS data id, and IncreaseRemainGBR gives back that and nothing else, so a rule with no record is given back nothing. Both takers record: DecreaseRemainGBR's two call sites, and modifyRemainBitRate, which is the live application-function path and debits directly. DecreaseRemainGBR also took the downlink first and, if the uplink did not fit, returned with the downlink already spent. The SM policy create arm returns on that error without restoring it, so the budget stayed short for the life of the session, once per refused request; the modify arm escaped it only by restoring from a snapshot it happened to take. It is both directions or neither now, which makes it atomic for every caller rather than for the one that remembered. Two adjacent defects in the same accounting are named in the pull request description and deliberately not fixed here: modifyRemainBitRate's own rollback dereferences a possibly-nil rate, and it restores only the uplink. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Edvin Lindqvist <edvin.lindqvist@forsway.com>
The ledger the previous commit added is reached from two HTTP handler goroutines for the same session: the application function path records a debit through modifyRemainBitRate, and the SM policy update path releases a rule through RemovePccRule. It had no lock. The tempting reading is that it is no worse off than its neighbours, since RemainGbrUL and RemainGbrDL are written with no lock either and have been for as long as they have existed. The failure modes are not the same size. A racy *float64 is a wrong number; a concurrent map write is a fatal runtime throw that takes the element down. New shared state should not turn an existing correctness race into a crash, so the map carries its own mutex -- a leaf, with nothing else acquired while it is held, so it cannot join a cycle with any lock a pull request in flight might add. The read and the delete are now one critical section, and the credit happens outside it. Two callers releasing the same rule would otherwise both read the entry before either removed it, and the budget would be credited twice for a debit that was taken once. Driven by a two-goroutine test rather than reasoned about: the single-goroutine tests pass either way, which is why raising the race count upstream would not have found this on its own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Edvin Lindqvist <edvin.lindqvist@forsway.com>
1a94202 to
d0c4bae
Compare
|
Rebased onto #397 raises the pinned race gate from The tempting reading is that it is no worse off than its neighbours, since The read and the delete are one critical section now, with the credit applied outside it. Two callers releasing the same rule would otherwise both read the entry before either removed it, and the budget would be credited twice for a debit taken once.
Gates on |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Unresolved rollback and concurrency issues remain, including a critical downlink-only panic.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 2
Open (3)
Resolved since last review (1)
…icking Two more from review. The first is in the ledger the last commit added. The modify arm credited a rule's previous debit back, took the new one, and on failure restored the budget from the snapshot the credit returned. The credit also removes the ledger entry, and nothing put it back, so the budget was right again but the record of it was gone: the next release of that rule found nothing to credit and the aggregate shrank for the life of the session. Fixing that exposed a second defect in the same three lines. The restore assigned the snapshot *pointers* onto the session rather than writing through the ones it already held. Those snapshots are nil when there was nothing to credit, so the failure path installed a nil budget -- read downstream as no limit at all, not as zero -- and the ledger makes that more reachable than it was, because there are now more ways for the credit to find nothing. Both are gone: ReplaceGbrDebit does the whole exchange, restores through the session's own pointers and re-records the prior debit, so the call site has no opportunity to get either wrong. Separately, modifyRemainBitRate's rollback dereferenced qosData.GbrUl with no guard. On a downlink-only request the uplink is never touched and that field is unset, and an unset NullableString's Get() is nil, so an exhausted downlink budget panicked instead of returning the authorization error. It now gives back only the direction it actually took, through the accessor that answers "" rather than dereferencing. This was named as pre-existing in the description of an earlier round, which was not enough: widening the GBR path past 5QI 4 is what makes it reachable, and that is this branch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Edvin Lindqvist <edvin.lindqvist@forsway.com>
|
Both right, and the first is a defect in the ledger I added in the previous round rather than one this branch merely exposes. The failed modify path lost the ledger entry. The arm credited the rule's previous debit back, took the new one, and on failure restored the budget from the snapshot the credit returned. But the credit also removes the ledger entry, and nothing put it back — so the budget was correct again while the record of it was gone, and the next release of that rule found nothing to credit. The aggregate shrank for the life of the session, silently. Fixing it exposed a second defect in the same three lines, which is the part I would not have found from the report alone. The restore assigned the snapshot pointers onto the session instead of writing through the ones it already held. Those snapshots are nil whenever there was nothing to credit, so the failure path installed a nil budget — read downstream as no limit at all, not as zero. The ledger makes that more reachable than it was before, because there are now more ways for the credit to find nothing. Both are gone. The rollback panic is real and "pre-existing" was not a good enough answer. I named it in an earlier round's description as a known adjacent defect; your point stands that widening the GBR path past 5QI 4 is what makes it reachable, and that is this branch. On a downlink-only request the uplink is never touched, Three tests, each driven through the real path and each mutation-verified: the ledger survives a refused modification and the rule still credits back on release; the budget pointers are rewritten rather than replaced; and a downlink-only request against an exhausted budget returns a problem detail instead of panicking. Worth recording about that verification: my first mutation run on the ledger fix passed, and it was a compile error — removing the restore left a variable unused, and the filter over the test output swallowed the build failure so an empty result read as green. Re-run building first and unfiltered, it fails as it should. Gates: |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Critical concurrency gaps can leave GBR budget debits and ledger entries inconsistent during concurrent modification or removal.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 2
Open (2)
Review found the ledger mutex guarding individual map accesses rather than the sequence they belong to. Between ReplaceGbrDebit's credit and its record another handler could claim the same QoS data id, and the debit written afterwards then belonged to a rule already released -- the aggregate staying short with nothing recorded to credit it back. The lock is now held across the whole exchange, and every budget mutation in this package is under it: IncreaseRemainGBR, DecreaseRemainGBR and the replace that composes them, with unexported variants for the callers that already hold it. Holding it across the exchange alone was not enough, and the concurrency test written to prove the fix is what showed it. IncreaseRemainGBR still credited outside the lock while ReplaceGbrDebit mutated the same budget inside it, so the two raced on the *float64 -- a lock only the newest caller takes reads as protection while providing none. What this does not cover, stated rather than implied: modifyRemainBitRate changes the aggregate directly from the producer, outside this lock. The budget has never been transactional -- upstream has no lock on it at all and three paths mutate it -- so that gap is pre-existing rather than introduced here, and closing it properly is a per-session transaction of the kind pcf#392 proposes. This commit closes the window this branch opened, not that one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Edvin Lindqvist <edvin.lindqvist@forsway.com>
|
Right, and the fix I reached for first was wrong in the way the finding predicts. The transaction gap is real. The mutex guarded individual map accesses, not the sequence they belong to, so between Holding the lock across the exchange alone was not enough, and the concurrency test written to prove the fix is what caught that. Worth saying that the test failed once for its own arithmetic before it failed for the code: the fixture recorded a debit while setting the budget as if nothing had been taken, so the invariant never held at the start. The comment in it now says so, because the next reader will build the same fixture. What this does not cover, and I would rather name it than let a half-lock read as complete. Gates on |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
GBR debit recording can race removal and record rates for directions that were not actually debited.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (1)
Resolved since last review (2)
| // Recorded only once both directions have been taken. The rates on qosData are what this | ||
| // function actually debited -- it writes back what it could take, which may be less than was | ||
| // asked for -- so this is the exact amount IncreaseRemainGBR has to give back. | ||
| smPolicy.RecordGbrDebit(qosData.QosId, qosData.GetGbrUl(), qosData.GetGbrDl()) |
…ng owed credits modifyRemainBitRate recorded both directions from the QoS data even when it debited one of them or neither. The rates on a stored QosData are not a record of what was charged: two of this function's five call sites read an existing entry out of the policy decision, where the rates may have come from the slice policy and been debited by nobody. A downlink-only update against such an entry entered its uplink rate in the ledger, and releasing the rule then credited an aggregate that was never charged -- the defect the ledger exists to prevent, arriving through the write instead of the read. Only the directions this call took are recorded now, and they are merged rather than replacing the entry. Replacing it would drop a debit an earlier operation genuinely took on the other direction. The test written for that found a second defect, this one in IncreaseRemainGBR. It still returned early when the policy decision or its QosDecs map was absent -- guards that belonged to the version reading rates out of the decision. With the ledger as the record they mean a debit that was taken goes uncredited whenever the decision entry has already gone, silently and for the life of the session. That is reachable beyond the test: RemovePccRule sets QosDecs to nil once the last entry is deleted, so a rule referencing two QoS data ids would skip the credit for the second. RemovePccRule's own guard has the same shape and is pre-existing; it is named in the pull request rather than widened into here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Edvin Lindqvist <edvin.lindqvist@forsway.com>
|
Right, and reachable by a route worth spelling out: two of Only the directions this call actually took are recorded now, and they are merged rather than replacing the entry. Replacing it would have been a second bug in the other direction: an earlier operation that debited only the uplink would have its record dropped by a later downlink-only one, and that debit would never be credited back. The test written for it found a second defect, in code this branch added. That one is reachable beyond the fixture: Which points at something I am not changing here: Both fixes mutation-verified: recording both directions again inflates the aggregate by the 5 Mbps that was never debited, and restoring the guards leaves the owed downlink credit unpaid. Gates on |


What
Two changes, together because the first does nothing without the second, plus one consequence of
the second that had to come with it.
1.
makeQosDesccarries the guaranteed rates. It built aQosDatafrom the polled slicepolicy with the 5QI, ARP and maximum bit rates, and dropped any guaranteed rate, so a slice policy
could express only a ceiling. It now carries
GbrUlandGbrDlthe same way it carriesMaxBrUland
MaxBrDl.2. The PCF decided whether a flow is GBR with
Var5qi <= 4, in seven places. That is not the3GPP definition. TS 23.501 table 5.7.4-1 gives a GBR resource type to 5QI 1 to 4, 65 to 67 and 71
to 76, and a delay-critical GBR resource type to 82 to 90. So 5QI 66 or 82 are mishandled today,
silently: a guaranteed rate the AF requests is neither authorised on the QoS data nor budgeted
against the UE's aggregate.
context.IsStandardisedGbr5QIreads the table instead.3.
util.MediaTypeTo5qiMapis now read checked. This is forced by 2 rather than chosen, and itis the one place where behaviour changes for an input that is not a GBR 5QI, so it is worth stating
plainly. The map was read unchecked at both mapping sites, so a media type outside the enum yielded
a 5QI of 0 — and
<= 4accepted it, meaning an AF sending an unrecognised media type had itsrequested rates applied under a value TS 23.501 does not assign. Reading the table instead would
have silently stopped applying them. So the lookup is checked and an unmapped media type keeps the
documented default of 9, which leaves no behaviour difference for any input the enum can produce.
TestMediaTypeTo5qiMapCoversEveryMediaTypepins the map as total overmodels.AllowedMediaTypeEnumValues, since that totality is the only reason the default wasunreachable for valid input.
Why all seven had to move together
Five of the seven are on the policy authorization path, where the 5QI is derived from the AF's
media type and is therefore always a standardised value — in practice always 1, 2 or 9. Three of
those five decide for a newly created PCC rule and two for an existing one: the same question
either side of a found-or-create branch. Fixing only the create arms would leave an AF's second
request for a rule answered differently from its first.
The remaining two are the aggregate budget's two directions, and they are a pair for the same
reason.
DecreaseRemainGBRdebits a requested guaranteed rate against the UE's aggregate;IncreaseRemainGBRcredits it back whenRemovePccRulereleases the rule. Moving only the debitwould leave the credit reading
<= 4, so a rate debited for a 5QI of 66 — which is exactly whatthis change starts doing — would never be given back, and the aggregate would shrink by that rate
once per rule, permanently. Neither gate fires for such a 5QI today, so the pair is consistent
before and after; it is splitting them that would introduce the leak. Thanks to the review that
caught this while the two were split.
context/ue.go:373context/ue.go:402producer/policyauthorization.go:362postAppSessCtxProcedureproducer/policyauthorization.go:387producer/policyauthorization.go:655handleCombinedMediaSubComponentsproducer/policyauthorization.go:1045ModAppSessionContextProcedureproducer/policyauthorization.go:1062Tests
Each test drives a call site rather than the helper, so what is under test is the decision and not
a table lookup. Each was checked by reverting the change under it and watching it fail, not only by
watching it pass:
TestDecreaseRemainGBRBudgetsGbr5QIAboveFour— a 5QI of 66 returns the requested rates anddecrements the aggregate budget. Reverted: empty rates and an untouched budget.
TestRemovePccRuleRestoresBudgetForGbr5QIAboveFour— releasing that rule credits the same rateback. Reverted: the budget stays short by the released rate, for good.
TestDecreaseThenRemoveLeavesAggregateUnchanged— the invariant the pair exists to keep, statedend to end: allocate then release leaves the aggregate where it started. It fails first if the
debit never happened, so it cannot pass by both directions doing nothing.
TestDecreaseRemainGBRLeavesNonGbr5QIUnbudgetedandTestRemovePccRuleLeavesBudgetAloneForNonGbr5QI— the mirror cases, so neither direction canlater be widened into treating everything as guaranteed.
TestHandleCombinedMediaSubComponentsAuthorisesGbr5QIAboveFour— a 5QI of 66 is authorised aguaranteed rate on the QoS data that is stored. Reverted: empty.
TestMakeQosDescCarriesGuaranteedBitRatesandTestMakeQosDescLeavesUnconfiguredGuaranteedRatesUnset— a configured guarantee is carried through, and an unconfigured one is not invented from the
maximum.
TestMediaTypeTo5qiMapCoversEveryMediaType— the totality that makes 3 a no-op for valid input;verified by deleting an entry and watching it fail.
TestIsStandardisedGbr5QIasserts the full sets from the table, including the Non-GBR values thatmust stay out. That list now includes 5QI 10, the Rel-17 satellite value with an 1100 ms packet
delay budget — the one standardised value the test previously left uncovered.
Gates run:
make test(race and coverage, all nine packages green),golangci-lint v2.13.2— theversion
main.ymlpins rather than the Makefile'slatestdefault — 0 issues, andmake check-reusecompliant.Dependency
nfConfigApi.PccQos.GbrUl/GbrDlcome from openapi #176, released in v2.2.2.mainalreadyrequires v2.2.2, so this PR changes no pin.
Deliberately not included
Three of these are pre-existing defects in the same accounting. None is this change's, each wants
its own fix, but the first two widen slightly in reach here, so they are named rather than left
implicit.
producer/smpolicy.gorestoresRemainGbrDL/RemainGbrULfromIncreaseRemainGBR's returnvalues, which are nil whenever the previous rate was unset — and a nil budget reads downstream as
no limit rather than as zero. The create arm has no rollback at all, so a request that passes on
DL and fails on UL leaves DL debited. Both were unreachable for a 5QI above 4 before, because the
old gate meant
DecreaseRemainGBRcould not fail for one.rule that comes from the polled slice policy, but
RemovePccRulecredits whatever guaranteedrate the QoS data carries — which, after change 1, is no longer always empty. Where the
subscription supplies an aggregate GBR, releasing such a rule can inflate the budget past it. The
design question underneath is whether slice-configured guarantees should be budgeted at all,
which is why it is not settled here.
it first, so an AF re-requesting a rule debits twice and only the last value is credited on
release. Inert on this path, where the media type maps to a 5QI of 1, 2 or 9 only.
carries its own QoS characteristics, so what would settle it is the presence of guaranteed rates.
Nothing in the PCF has to make that decision today:
makeQosDesccarries the configured ratesthrough without consulting the 5QI, and the SMF's
CreateDedicatedQosQerkeys off whether therates are present rather than off the 5QI. An exported helper with no caller would only be a
guess at the shape of that caller, so it is left for whichever change needs it.
a configuration-validation change in its own right. Opened as feat: warn when a guaranteed rate is configured against a Non-GBR 5QI #391, stacked on this one.
GBR on the QER in
CreateDedicatedQosQer, which the policy-update path reaches, while theestablishment path's
CreatePccRuleQersets MBR only. A slice-configured guarantee thereforetakes effect on a policy change and not at session establishment. That is an SMF gap, not this
change's.