QuantumBNG IPoE Community Edition · Alpha

The forwarding platform

Line-rate IPoE forwarding, policed and accounted, on commodity x86.

A disaggregated BNG that turns raw subscriber packets into managed, authenticated, rate-limited, accounted sessions — and scales by adding nodes.

~100k
Subscribers / node
RFC 2698
Two-rate policing
IPv4
Phase 1
Deny
by default
Operator / carrier systems — RADIUS · OSS/BSS · NMS Controller (Node.js) — the brain Session Manager · embedded DHCP · AAA client accounting · SQLite persistence · REST API gRPC (can cross hosts) vpp_bridge (Go) — the translator turns high-level requests into VPP API calls VPP binary API (shared memory) VPP data plane (DPDK) — the muscle session table · inline policing · captive filter Access NIC ⇄ Core NIC · Intel E810 Edge routers → → Upstream / core Start-up order: VPP → vpp_bridge → controller

The system at a glance

Two planes, three cooperating processes

The BNG is not one program. Knowing which process does what is the foundation for operating and troubleshooting it. The data plane forwards; the control plane thinks; a small translator connects them.

controller · Node.js

The brain

Holds everything intelligent: the Session Manager state machine, the embedded DHCP server and address pools, the AAA client, the accounting engine, persistence, and the REST API you and your systems use.

vpp_bridge · Go

The translator

A small process that connects the controller to VPP over gRPC. The controller makes a handful of high-level requests — "add this session," "change this rate," "give me the counters" — and the bridge turns them into VPP calls.

VPP · DPDK

The muscle

Runs in userspace on DPDK, driving an access-facing and a core-facing NIC. Once a subscriber is set up, every one of their packets is handled here at line rate, with no involvement from the controller.

Fast path vs. slow path.

In steady state the controller sees none of a connected subscriber's traffic. Only two tiny classes of packet are ever punted up: DHCP from an unknown subscriber, and inbound RADIUS CoA. Everything else stays in VPP and is forwarded, policed, filtered, and counted — which is why the box forwards at line rate while the controller's CPU stays low with a full session table.

The data plane

Every packet, one session lookup

Because the access network is L3-routed, the BNG identifies each subscriber by the IP it assigned them — a /32 host address. A single lookup of the session pulls everything the data plane needs into one place: the anti-spoof reference, the captive flag, and the two rate meters. No separate firewall table, no separate rate-limit table.

  • Deny by default — an unprovisioned address gets nothing
  • Anti-spoof on every upstream packet — source IP must match the session
  • Captive check — behind the walled garden, only portal traffic survives
  • Shared edge-router MAC keeps the neighbour table small at 100k subs
Upstream: subscriber → internet 1 · Look up session by source IP 2 · Anti-spoof: source IP = assigned IP 3 · DHCP intercept → punt renew / release 4 · Captive check (walled garden) 5 · Meter → green / yellow / red 6 · Forward toward core / uplink NIC Downstream is the mirror image — looked up by destination IP.

Rate limiting

Green, yellow, red — a measurement, not just a decision

Every subscriber gets two rate limiters — upstream and downstream — implementing the RFC 2698 two-rate, three-colour policing model. Two numbers define each direction: the committed rate (CIR) they're guaranteed, and the peak rate (PIR) they may burst to.

ColourMeaningWhat happensOn the bill?
GreenWithin the committed rate (≤ CIR)Forwarded, countedYes
YellowBursting above CIR, within peak (≤ PIR)Forwarded, countedYes
RedExceeds the peak rate (> PIR)Dropped, countedNo (diagnostics only)

A far richer per-subscriber picture

The data plane keeps a full set of counters split by colour, by direction, and by unit (bytes and packets). You can see not just how much a subscriber used, but how much was in-contract, how much was burst, and how much was shed at the cap — in each direction. A climbing red counter is both an upsell signal and an abuse signal.

Node-wide bands, one cheap query

Alongside the per-subscriber counters, the data plane keeps six node-wide band counters (green/yellow/red × up/down). You can read what the whole box is doing by QoS band without walking the session table — ideal for a high-frequency dashboard.

The control plane

The subscriber lifecycle, as a state machine

At the heart of the controller is the Session Manager — an explicit state machine that models the life of every subscriber. DHCP and authentication are a single coordinated act, which is why the BNG embeds its own DHCP server rather than relaying to an external one.

StateMeaning
AUTHENTICATINGDHCP Discover arrived; asking AAA whether to admit. Transient.
OFFERINGAAA said yes; address offered, data plane pre-programmed. Transient.
CONNECTEDFully online. Traffic flows at line rate; accounting and timers run.
CAPTIVEBehind the walled garden — keeps its IP, reaches only the portal.
TERMINATINGBeing torn down. Final accounting sent, then the session is removed.

Onboarding: DHCP and AAA are one act

A Discover is punted and authenticated; on accept the controller resolves the plan, allocates an address, programs the data plane, and offers the lease; the subscriber's Request creates the lease, starts accounting, and arms timers. On an AAA reject, the subscriber isn't dropped — they're landed directly in CAPTIVE so they can reach the portal and sign up.

Teardown order is a correctness rule

Teardown reads the final counters from the data plane first, sends the closing accounting record second, and only then removes the session — stamping a standard terminate cause (User-Request, Idle-Timeout, Session-Timeout, Admin-Reset, Service-Unavailable) so your billing system knows why the session ended.

No session is ever unpoliced.

If AAA returns explicit rates, they're used; if it names a plan, the local plan table is used; if it returns neither, a default (Bronze) plan is applied and a warning is logged. A connected subscriber can also be re-rated in place — editing a plan walks the session table and updates every subscriber on it, with no re-DHCP and no interruption.

Captive portal & the prepaid model

Expiry demotes to captive — it doesn't disconnect

The captive portal is central to the target business: prepaid fixed-wireless. When a subscriber is in CAPTIVE state, the data plane permits exactly three things and silently drops the rest — DNS, HTTP, and HTTPS to the portal.

The redirect needs no in-path HTTP interception. A captive subscriber's lease hands out the portal's DNS server as their only resolver, and that server answers every lookup with the portal's address. Combined with the walled garden, any site they type resolves to — and can only reach — the portal.

Why demote, not disconnect? Keeping their IP and pushing them behind the portal means their next browser action is a "top up to continue" page — the exact conversion path a prepaid operator depends on. Only a Release, idle-out, or explicit disconnect actually removes the session.

Walled garden DNS → portal HTTP → portal HTTPS → portal ✕ everything else silently dropped Same IP whether connected or captive

Accounting

Usage becomes billable records

The BNG emits three kinds of record, and two details shape what the numbers mean.

Start

Sent when a subscriber connects, counters at zero.

Interim

Sent periodically during the session, carrying cumulative usage.

Stop

Sent at teardown, carrying final usage and the terminate cause.

Only green + yellow are billed

Red traffic was dropped at the policer — the subscriber never received it — so it's excluded from the billed octet counts. Red is still reported through the API for diagnostics; it just isn't on the bill.

Exact into the petabyte range

VPP counts in 64-bit; RADIUS octet fields are 32-bit, so each count is split into the octet field plus a "gigawords" field (units of 4 GB). Byte counts stay exact well past the petabyte range. Each session carries a stable accounting ID and echoes back any opaque Class value verbatim.

Alpha note.

The counter substrate — per-colour, per-direction byte and packet counts refreshed from the data plane — is real and running today. Assembling those counts into RADIUS accounting packets on the wire is part of the deferred production RADIUS client.

Timers, scale & recovery

Restarts don't drop subscribers

Because the controller and data plane are separate processes, a restart of one must not disconnect subscribers carried by the other. Session state is durable — written to a local database on every state change — and the things you can't save (live timers, sockets) are rebuilt on startup from absolute expiry timestamps. A deadline already in the past just fires on the next pass.

  • Controller restarts, data plane up: re-arm timers from saved deadlines — VPP keeps the live sessions
  • Both fresh: rebuild state, then re-program every session so the two match
  • Data plane diverged: tear down untrusted state, re-program from the controller's records
  • Upgrades preserve live sessions; stale sessions past a recovery-age limit close cleanly (cause 15)

What bounds a node

Three time-based jobs run for every connected subscriber — interim accounting, session expiry, idle detection. Rather than hundreds of thousands of timers, the BNG folds them into a single batched loop that reads all due counters in one bulk request, writes state once, and emits the records that are due.

  • ~100,000 concurrent subscribers on R360-class hardware
  • The limit is memory / cache behaviour, not raw CPU
  • Idle detection needs no timer — it's derived from the counters
  • Growth is horizontal: add a node under the same config

Operating the BNG

What to watch — all on the management NIC

Everything here is available via the REST API and Prometheus. GET /bng/health rolls the box up to a single status — ok, degraded, or fault — using a deliberate rule.

fault

The data plane (VPP) is down, or all RADIUS endpoints are unreachable. Subscribers are affected; act now.

degraded

Exactly one of a redundant pair of RADIUS endpoints is unreachable. Still serving; investigate.

ok

Serving normally. A full address pool is reported but doesn't by itself drive the status to fault.

Two read paths for counters

The accounting view (GET /bng/sessions) is the billing-grade snapshot, refreshed on the interim cadence. The telemetry view (GET /bng/counters) is a pure read straight from the data plane — it takes no locks and triggers no save, so you can poll it as fast as you like for live dashboards.

The metrics that tell the story

Sessions by state, per-subscriber red counters, node-wide QoS bands, DHCP protocol counters, pool utilisation, and the controller's own save timing — your early warning that a node is approaching its ceiling. Structured JSON logs go to stdout; Prometheus is scraped from /metrics.

Scope & roadmap

Deliberate edges, and named next steps

Two different boundaries apply. Scope decisions are intentional edges of the product line — stable across releases. Caveats are specific to this Community-Edition Alpha, each with a defined path forward.

Product-line scope

  • IPoE only — no PPPoE, no 802.1X/EAP
  • L3-routed access — subscribers keyed by IP; no per-subscriber VLANs or QinQ
  • Policing, not shaping — RFC 2698 drop-on-red; queue-based AQM is out of scope
  • Pull-based notifications — Prometheus + Alertmanager replace SNMP traps
  • No hard data-plane volume cap — RADIUS stays the authority for policy

On the roadmap

  • Production RADIUS client — live sockets, retransmit/failover, CoA/Disconnect listener, accounting assembly, the eight QoS vendor attributes (PEN 65664)
  • IPv6 — dual-stack / IPv6-only, DHCPv6, prefix delegation
  • Per-worker session tables — a path toward ~400k–500k per node

Today the box runs a local AAA provider (open or gated) and operates standalone with no RADIUS server — exactly the Community-Edition free-tier on-ramp.

Put a line-rate BNG on commodity hardware

Download the Community Edition and stand up the forwarding stack standalone — then add QuantumTouch to operate it.