UE-requested filter modification: add/delete/replace (#22) - #56
Conversation
ca3ff85 to
d9fb57d
Compare
0266ba5 to
8efa205
Compare
d9fb57d to
0962fff
Compare
| {PCC1, _} = smf_pcc_context:gx_events_to_pcc_ctx(Events, remove, RuleBase, PCC0), | ||
| {PCC2, _} = smf_pcc_context:gx_events_to_pcc_ctx(Events, install, RuleBase, PCC1), |
There was a problem hiding this comment.
Wouldn't we also need to deliver the result of the operation somehow? Currently it seems that any failure is ignored, right? that might be correct, but better check.
There was a problem hiding this comment.
There can be errors, and dropping them was wrong. Fixed in f8411d6.
gx_events_to_pcc_ctx/4 returns {PCC, Errors} where Errors is non-empty whenever the CCA references a predefined rule or rulebase this PGW has no local configuration for — install_preconf_rule/4 and install_preconf_rulebase/5 in smf_pcc_context produce {not_found, {rule, Name}} / {not_found, {rulebase, Name}}. Only Charging-Rule-Definition (dynamic rules) can never fail; it goes straight to update_pcc_rule/4. So this is a routine PCRF/PCEF provisioning mismatch, not an unreachable state.
TS 29.212 §4.5.12: for PULL provisioning — rules arriving in a CCA, which is this path — failures at any stage are reported in a new CCR with PCC-Rule-Status = INACTIVE, because the answer that could have carried them is the CCA we just processed. Dropping them left the PCRF believing a rule was active that we never installed, for the life of the session.
It was not only a reporting gap: PCC2 feeds detect_removed_bearers/3 and the TFT rebuild, so a silently-missing rule can change whether we emit a Delete or an Update Bearer, and with which filters — while still answering the UE's command as success.
New report_pcc_failures/4 builds the Charging-Rule-Report with the existing smf_gsn_lib:pcc_events_to_charging_rule_report/1 and issues a fire-and-forget CCR-Update, matching the establishment path in smf_gtp_gsn_lib and gtp_context:rar_report_alloc_failures/4. Wired into all four UE bearer procedures (the QoS-change one in #57, 0376a35).
Install pass only. §4.5.12 states removal never fails — the PCEF always accepts a Charging-Rule-Remove — so a {not_found, {rule, _}} from the remove pass means the requested end state already holds. Those two sites keep _ with a comment saying why.
New e2e ue_add_packet_filters_reports_unknown_rule: the CCA installs ded-rule-2 (dynamic, applies) plus an unknown predefined rule, and asserts the Update Bearer still goes out AND exactly one Charging-Rule-Report with a Rule-Failure-Code naming the rule INACTIVE. Verified red without the production change (Failures = []). Full pgw_SUITE 139/139.
One thing I did not change: pcc_events_to_charging_rule_report/2 maps both not_found kinds to RATING_GROUP_ERROR (2) where §5.3.38 has UNKNOWN_RULE_NAME (1). That is pre-existing and affects the establishment path too, so it seemed out of scope here — say the word and I'll fix it separately.
| ok <- async_m:lift(ccr_result(Result)), | ||
| RuleBase = smf_charging:rulebase(), | ||
| %% An add only installs (nothing to remove). | ||
| {PCC1, _} = smf_pcc_context:gx_events_to_pcc_ctx(Events, install, RuleBase, PCC0), |
There was a problem hiding this comment.
Here too, do we need to report failures in any way or shape?
There was a problem hiding this comment.
Same gap, same fix — see the reply on the delete site above. report_pcc_failures/4 is wired into this procedure too (f8411d6); an add has no remove pass, so its single gx_events_to_pcc_ctx/4 call now reports.
| {PCC1, _} = smf_pcc_context:gx_events_to_pcc_ctx(Events, remove, RuleBase, PCC0), | ||
| {PCC2, _} = smf_pcc_context:gx_events_to_pcc_ctx(Events, install, RuleBase, PCC1), |
There was a problem hiding this comment.
Here too, do we need to report failures in any way or shape?
There was a problem hiding this comment.
Same gap, same fix — see the reply on the delete site above. Wired here too in f8411d6; as with delete, the remove pass keeps _ because §4.5.12 says removal never fails, and only the install pass reports.
| if map_size(GxReport) /= 0 -> | ||
| case smf_aaa_pcf:ccr_update(PCF0, Session0, GxReport, | ||
| ReqOpts#{async => true}) of | ||
| {ok, PCF, Session, _} -> {PCF, Session}; | ||
| _ -> {PCF0, Session0} | ||
| end; | ||
| true -> | ||
| {PCF0, Session0} | ||
| end. |
There was a problem hiding this comment.
this could be a maybe ... else ... end construct, right?
There was a problem hiding this comment.
It can, and it reads better — both failure paths return the same {PCF0, Session0}, which is exactly the shape maybe/else collapses. Done in ae46b60:
report_pcc_failures(PCCErrors, PCF0, Session0, ReqOpts) ->
maybe
GxReport = smf_gsn_lib:pcc_events_to_charging_rule_report(PCCErrors),
true ?= map_size(GxReport) /= 0,
{ok, PCF, Session, _} ?=
smf_aaa_pcf:ccr_update(PCF0, Session0, GxReport, ReqOpts#{async => true}),
{PCF, Session}
else
_ -> {PCF0, Session0}
end.One thing worth your call: I added -feature(maybe_expr, enable). to the module. On our OTP 28.3 target it is a no-op — maybe_expr has been on by default since OTP 27, which is why rebar.config:31 has to disable it for ra. But rebar.config also declares {minimum_otp_vsn, "26.2"}, and on 26.x the feature is off by default, so without the directive this module would stop compiling there. Verified both forms build clean on 28.3 with warnings_as_errors.
I could not test against 26.2 — this machine only has 28.3 and 29 installed — so I do not know whether the rest of the tree still builds there anyway. If that floor is stale (issues #1 and #9 both point at OTP-29), drop the line and I will re-push.
This is the first use of maybe in the tree, so if you would rather it stayed uniform with the surrounding case/if style, say so and I will revert to the previous form.
pgw_SUITE 139/139 at the top of the stack after the restack.
There was a problem hiding this comment.
Dropped, and the baseline moved to match — e0193cf:
rebar.config:{minimum_otp_vsn, "26.2"}->"28"apps/smf_aaa/rebar.config: same (its own floor still said 26.2, so the umbrella claim would not have been repo-wide)-feature(maybe_expr, enable).removed frompgw_s5s8
Verified the module still builds without the directive on 28.3 with warnings_as_errors, which is the point — maybe_expr is default-on from OTP 27.
Two 26.2 leftovers I did not touch, both inherited from the upstream ergw_aaa import: apps/smf_aaa/.github/workflows/main.yml (otp: [26.2] — inert, only root .github/workflows runs) and the erlang version badge in apps/smf_aaa/README.md. Say the word if you want those aligned too, or folded into #9.
pgw_SUITE 139/139 at the top of the stack after the restack.
The UE-requested bearer resource modification filter operations (#22), on the whole-pipeline async invoke foundation from #48:
delete_packet_filters— empties a TFT → Delete Bearer; leaves survivors → Update Beareradd_packet_filters— Update Bearer (Gx CCR-U ADDITION)replace_packet_filters— Update Bearer (Gx CCR-U MODIFICATION)Each procedure calls
smf_aaa_pcf:invoke(#{pipeline_async => true}), awaits one folded pipeline result, and drives the PTI-correlated bearer procedure (with a second PFCP-modify await on the Update path).Supersedes the per-increment PRs #52–#55 (re-authored onto
invoke(pipeline_async)and collapsed here) and drops #49 (its diameter-bridge CCR-U enabler is replaced by the #48 foundation).Packet-Filter-Information/Packet-Filter-Operationsmf_tftadd/modify/replace filter-group helpers +pf_ids_to_sdfpgw_SUITE132/132 + Gx wire round-trip testsIncrement 6 (requested-QoS/GBR change) remains open on #22.