Skip to content

run the Gx RAR apply as an async procedure - #67

Merged
next-nf merged 1 commit into
mainfrom
async-rar-apply-modify
Jul 27, 2026
Merged

run the Gx RAR apply as an async procedure#67
next-nf merged 1 commit into
mainfrom
async-rar-apply-modify

Conversation

@next-nf

@next-nf next-nf commented Jul 26, 2026

Copy link
Copy Markdown
Owner

First batch of the "~11 blocking modify_session sites" conversion, and the completion
of what #62 started: the RAA now goes out on validation, but the apply it queues still
blocked the FSM on two PFCP round-trips.

Two sites, both inside the single handle_event(internal, {gx_rar_apply, …}) clause —
the remove pass and the install pass. No caller ripple: one internal event, one emitter.
The remaining batches are filed with their call-graph analysis as #64 (apply_bearer_change/5
plus its four callers across three interfaces), #65 (six pgw_s5s8 bearer helpers, including
one inside an ie_foldl that needs a monadic fold) and #66 (ggsn_gn Update PDP).

How blocking it was

Sharper than expected. With the old code the new test fails with
{timeout, {sys, get_state, [<0.2032.0>]}} — the context cannot answer a system message,
because it is blocked inside smf_sx_node:call/2 for the whole PFCP retransmit window.

What's here

  • gx_rar_apply_proc/3, a two-await async_m procedure: PFCP modify (remove) → the Gy
    charging round → PFCP modify (install) → allocation-failure CCR-U → write-back. The body
    is the blocking code moved across; the two case-wrappers around modify_session/5 are
    gone because failures now travel the error channel.
  • Error handling improves as a side effect. The blocking code did
    throw(Err#ctx_err{context = …, tunnel = …}) from a gen_statem callback with no enclosing
    try, so that path crashed the context with bad_return_from_state_function instead of
    producing an error reply. gx_rar_apply_err/3 now applies the same decoration and routes
    through handle_ctx_error/4.
  • The {gx_rar_apply, …} gate clause stays — it is what stops a second procedure starting.

A correction to #62's reasoning

#62's PR body argued that multiple in-flight RARs converge without extra state, because each
validates on top of the previous one's committed PCC2 and the applies run FIFO. That is
wrong once the apply is async
, and the existing gx_rar test caught it: RAR #2 validates and
commits PCC2#2 while apply #1 is parked, then apply #1's write-back lands carrying PCC4#1
derived from its own captured PCC2#1 and clobbers the removal. gx_rar failed on
?equal(false, maps:is_key(<<"r-0002">>, PCR2)) in all three interfaces.

The convergence argument only holds once all applies have run; it says nothing about the
window between validation #2 and apply #2. The fix is the rar_apply_pending flag I had
designed for #62 and then dropped as unnecessary — one apply outstanding at a time, so a Gx RAR
arriving in that window is postponed. It lives in the gen_statem State, like async_pending,
so clearing it is a state-term change that re-delivers the postponed RARs.

This is deliberately much narrower than gating on async_pending: a RAR arriving while an
unrelated procedure is parked is still answered at once, which is what #62 bought and what
gx_rar_answers_raa_while_parked covers.

Test-suite consequence

gx_rar_gy_interaction asserted PFCP timer counts immediately after each RAA, in all three
suites. That encoded the old synchronous coupling: the RAA now acknowledges validation, not
resource allocation (TS 29.212 §4.5.12), so PFCP-side state lands shortly after it. Those six
assertions became bounded waits. Related: wait_until/3 moved from pgw_SUITE into
smf_test_lib and is imported via smf_test_lib.hrl, since all three suites now need it.

Worth noting the same assertions were already timing-sensitive after the change — saegw's copy
passed one run and failed the next — so the waits remove a real flake, not just a failure.

Testing

gx_rar_apply_is_async holds the UPF, injects a rule-installing Gx RAR and asserts
async_pending_size reaches 1 — the apply parks rather than blocking. Verified red against the
final test by reverting only the production files.

pgw_SUITE + ggsn_SUITE + saegw_s11_SUITE: 238 passed, 0 failures.

Stacked on #63. Merge bottom-up: #45#46#48#56#57#58#59#61#62#63 → this.

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.

1 participant