Appendix A: Quantum Controller v1.2.0 release notes

The following is the Quantum Controller team's own release notes, reproduced verbatim from github.com/Bluedot-Insight/bng/releases/tag/v1.2.0. This is the controller version bundled inside this QuantumBNG alpha.


Release v1.2.0

Overview

Standalone / free-tier release for Quantum BNG. The headline change is that the BNG can now run without a RADIUS server: a built-in local-AAA provider handles subscriber admission and tiering by line identity, making the product a self-contained BNG for small ISPs. This release also introduces a free-tier session cap (1,000 concurrent subscribers), DHCP lease-expiry timers, plan-edit propagation to live sessions, and a broader observability surface (DHCP reply-path counters, session-cap visibility, write-path timing).

It is also the first release-hardened build: the management API now requires authentication by default, the test-only endpoints ship disabled, and the binary distribution carries its own end-user license (distinct from the source license).

Built against quantum_core v1.4.0 and quantum_test v1.2.0 (v1.1.0 shipped against quantum_core v1.3.0 / quantum_test v1.1.0).

Licensing is not enabled in this product build (LICENSING_ENABLED := false); the free tier requires no activation license. The core licensing machinery is present but compiled out / stubbed.

New Features

Local-AAA Server — Standalone Operation (no RADIUS required)

A built-in AAA provider lets the BNG admit and tier subscribers with no external RADIUS server. Identity is the subscriber line (DHCP Option 82 circuit-id / remote-id), and per-line records drive the onboarding outcome:

  • active → accept (onboard at the record's plan)
  • suspended → captive (dunning / policy hold — walled garden, plan retained)
  • terminated → reject (dropped)

Two modes: open (flat-rate accept-all — the default) and gated (per-line policy). Captive-portal activation re-authenticates against the record and restores the subscriber's plan.

  • GET / PUT /bng/aaa/local — provider config (mode, default plan, unknown-line policy).
  • GET / PUT / DELETE /bng/aaa/local/subscribers/{line} — per-line records (status, plan, optional session_timeout / idle_timeout / interim_interval).
Free-Tier Session Cap

The product enforces a compiled 1,000 concurrent-subscriber limit in the VPP plugin dataplane (tamper-resistant, independent of the JS controller). Onboards past the cap are silently dropped with a rate-limited log — no NAK storm.

  • GET /bng/health reports sessions.onboard_refused (monotonic, climbs at the cap), plus sessions.max and sessions.at_cap sourced from the plugin.
DHCP Lease-Expiry Timers

A per-session lease timer reaps a subscriber whose CPE stops renewing (returns the address to the pool), closing a gap where an abandoned CAPTIVE or a CONNECTED-past-lease session could linger. The DHCP lease is now pool-driven and independent of any RADIUS Session-Timeout, so a Session-Timeout correctly drops an active subscriber to CAPTIVE while the lease stays valid.

Plan-Edit Propagation & Live Re-Tier
  • PUT /bng/plans/{name} now re-rates every live session on that plan in place (response reports re_rated / failed) — an edit reaches existing subscribers, not just new ones.
  • POST /bng/sessions/{ip}/plan — move a single live session to a different plan.
Expanded Observability
  • GET /bng/counters gains a dhcp block — reply-path counters (discovers_received, offers_emitted, requests_received, acks_emitted, naks_emitted), monotonic since controller start.
  • GET /bng/health gains persistence — interim-tick write-path timing (save_ms, write_lock_wait_ms) for spotting the DB-bound ceiling.

A Prometheus /bng/metrics endpoint is intentionally not provided — the JSON counters are designed to be scraped by the monitoring layer.

Security & Release Hardening
  • Authentication on by default (AUTH_REQUIRED_DEFAULT := true). The management API requires a Bearer API key; provision keys with create_api_key.sh. Keys are hashed at rest, role-based (read_only / read_write / admin_only), and hot-reloaded.
  • Test endpoints off by default (TEST_ENDPOINTS_DEFAULT := false). The /bng/_test/* and /quantum/_test/* routes are not mounted in the shipped product.
  • Binary distribution license. The .deb packages and install bundle ship an end-user license (LICENSE.txt) distinct from the source LICENSE.

API Changes

Quick index; detail is in the sections above.

Added

  • GET / PUT /bng/aaa/local
  • GET / PUT / DELETE /bng/aaa/local/subscribers/{line}
  • POST /bng/sessions/{ip}/plan — live re-tier

Changed

  • PUT /bng/plans/{name} — re-rates live sessions on the plan (re_rated / failed)
  • GET /bng/counters — adds the dhcp reply-path counter block
  • GET /bng/health — adds sessions.max / sessions.at_cap / sessions.onboard_refused and a persistence timing block
  • GET / PUT /bng/radius — the config surface is now inert (local-AAA is the backend): GET returns {active:false, …} and PUT returns 503 rather than storing config nothing consumes. To be re-enabled when the real RADIUS client ships.

Removed from the shipped surface (test endpoints off by default — see Breaking Changes)

  • PUT / GET / DELETE /bng/_test/radius/stub — RADIUS stub (dev / integration only)
  • POST /bng/_test/sessions/synthetic — synthetic session injection (scale / cap testing)
  • POST /quantum/_test/vpp/{switch}/force_resync and the other /quantum/_test/* fault-injection routes
  • Not deleted from the code — simply not mounted unless testEndpoints is re-enabled via /data/runtime_overrides.json.

Bug Fixes

  • Onboarding / churn robustness (issues #20, #21). Session dedup now keys on subscriber identity (MAC + circuit-id + remote-id), independent of the DHCP xid, so a re-DORA reuses the in-flight session instead of spawning a duplicate. This eliminates the duplicate-session accumulation seen under storm and churn load; storm tests reconcile cleanly at 1000/1000.
  • Lease vs Session-Timeout conflation. The DHCP lease had been derived from the RADIUS Session-Timeout, collapsing two independent clocks onto the same instant and (with the new lease timer) pre-empting the CONNECTED → CAPTIVE transition. The lease is now pool-driven and independent — see Lease-Expiry Timers above.

Breaking Changes

  • Management API now requires authentication. v1.1.0 shipped with auth disabled by default; v1.2.0 ships it enabled. Clients must present a Bearer API key, and at least one key must be provisioned (create_api_key.sh) before the API will accept requests. AUTH_REQUIRED_CONFIGURABLE remains true, so an operator can still opt out via runtime config for a trusted environment.
  • Test endpoints are off by default. The RADIUS stub and synthetic-session routes are no longer available in the shipped build unless explicitly re-enabled (/data/runtime_overrides.json{"testEndpoints": true}).
  • /bng/radius is inert. Configuring RADIUS via the API now returns 503; local-AAA is the AAA backend for this release.

Resolved Issues

Closed under the v1.2.0 milestone; see the sections above for detail.

  • 20 — onboarding performance under storm (identity/xid dedup)

  • 21 — duplicate sessions on re-DORA

  • 22 — DHCP reply-path counters / session-cap observability

Known Issues (controller-side)

  • Churn over-drain (#24), reported against v1.1.0 — believed addressed by the #20/#21 identity-dedup fix in this release (the v1.1.0 binary lacked it), but awaiting confirmation from a re-run of the churn-longevity harness against a v1.2.0 build. Note: session-dedup currently does offer-reuse; full tear-down replace-on-duplicate is a follow-on.
  • Production RADIUS client not yet shipped. Standalone deployments use local-AAA and need no RADIUS server; production RADIUS integration (auth, accounting, CoA) is targeted for a follow-on release. The /bng/radius API is inert until then.
  • sessions.max / sessions.at_cap require the plugin + vpp_bridge built with this release (the BngCapStatus RPC); against an older dataplane those two fields are omitted and /bng/health otherwise degrades gracefully.
  • Out-of-contract DSCP marking not yet implemented (issue #19). Traffic is metered and counted into green / yellow / red bands, but out-of-contract (yellow) packets are not yet DSCP-remarked. Forwarding is unaffected.