3. Test environment
3.1 Platform under test — hardware
| Server | 2-socket Intel Xeon E5-2640 v2 @ 2.00 GHz |
| Cores / threads | 16 cores (2 × 8), 1 thread per core — SMT disabled |
| Cache / NUMA | 40 MiB L3 (2 instances), 2 NUMA nodes |
| Memory | 31 GiB, with 8 × 1 GiB hugepages (all allocated to the dataplane) |
| Dataplane NICs | 2 × Intel XL710 40GbE backplane, [8086:1580] rev 01 |
| NIC driver | vfio-pci, both devices on NUMA node 0 |
| OS / kernel | Ubuntu 24.04.4 LTS, kernel 6.8.0-146-generic |
Full network controller inventory, read from dpdk-devbind --status on the
box under test. The XL710s are the only ports that carry subscriber traffic;
the rest are management and are listed so the inventory is complete:
| PCI | Controller chip | Interface | Driver | Role |
|---|---|---|---|---|
0000:01:00.0 |
Intel XL710 40GbE backplane [8086:1580] |
FortyGigabitEthernet1/0/0 |
vfio-pci |
Access — subscriber side |
0000:47:00.0 |
Intel XL710 40GbE backplane [8086:1580] |
FortyGigabitEthernet47/0/0 |
vfio-pci |
Uplink — core side |
0000:04:00.1 |
Intel DH8900CC Gigabit backplane [8086:043c] |
enp4s0f1 |
igb |
Management / harness SSH (the only active 1G port) |
0000:04:00.2-4 |
Intel DH8900CC Gigabit backplane [8086:043c] |
enp4s0f2-4 |
igb |
Unused |
0000:4a:00.0 |
Intel I350 Gigabit [8086:1521] |
enp74s0f0 |
igb |
Unused on this box |
0000:4a:00.1 |
Intel I350 Gigabit [8086:1521] |
enp74s0f1 |
igb |
Unused |
0000:04:00.0 |
Intel DH89XXCC QAT [8086:0434] |
— | — | Crypto accelerator, unused |
Both XL710 ports are backplane variants — this is a blade chassis, not a
box with pluggable optics. Neither the QAT accelerator nor any offload beyond
RSS is used on the forwarding path; no-tx-checksum-offload is set in §3.3, so
the per-packet cost in §5.7 is software forwarding cost.
What this hardware means for the numbers
The processor launched in 2013. The E5-2640 v2 is a 2.0 GHz Ivy Bridge-EP
part — two generations before DDR4, and roughly a decade behind anything a
customer would deploy new today. We state the platform prominently because it is
the most important context for every forwarding figure here: these are floors
measured on old silicon. A reader deploying current hardware can reason
upward from them.
Symmetric multithreading is disabled (1 thread per core), so each dataplane
worker is a physical core with no sibling contention — and equally no benefit
from SMT.
Core isolation is applied. The boot command line is:
default_hugepagesz=1G hugepagesz=1G hugepages=8 irqaffinity=0-1
isolcpus=2-6 nohz_full=2-6 rcu_nocbs=2-6
intel_pstate=disable processor.max_cstate=1 intel_idle.max_cstate=0 idle=poll
numa_balancing=disable hpet=disable mce=off tsc=reliable nmi_watchdog=0
intel_iommu=on iommu=pt
The kernel confirms it: /sys/devices/system/cpu/isolated reads 2-6, and all
five VPP workers sit on exactly that set with interrupts confined to cores 0–1.
An honest note on what isolation bought. We measured this platform both
without and with core isolation. It produced no throughput improvement. The
two isolated runs reproduce each other to within 0.2% on the single-worker
cells, and both sit 2.5–3.9% below the single un-isolated run; the two-worker
cells agree within 1.1% across all three. We are not claiming isolation harms
forwarding — the un-isolated condition was measured once, and nohz_full /
rcu_nocbs carry their own overheads we did not isolate. The honest conclusion
is that on a box where nothing else contends for the worker cores, isolation
removes contention that was not there. It remains correct practice because it
protects against future contention, not because it raised these figures.
NUMA locality is correct. The dataplane uses main-core 1 with
corelist-workers 2-6, and CPUs 0–6 all sit on NUMA node 0 — the same node as
both NICs. No cross-socket traffic on the forwarding path.
3.2 Platform under test — software
| Installer bundle | quantumtouch-installer-1.4.0-13 |
| BNG plugin | 0.10.36, commit 9a12835, clean tree |
| Controller | quantum-bng-controller:1.4.0 (container) |
| quantum_core | v1.6.0 |
| VPP | v25.10.0-23~g744d3c715 |
| CPESIM | 0.4.17 |
| Metrics | Prometheus (container) |
3.3 Dataplane configuration
Taken verbatim from the running /etc/vpp/startup.conf:
cpu { main-core 1 corelist-workers 2-6 }
memory { main-heap-size 2G }
buffers { buffers-per-numa 1048576 default data-size 2048 }
statseg { size 1024M }
dpdk { uio-driver vfio-pci no-multi-seg no-tx-checksum-offload
dev 0000:01:00.0 { num-rx-queues 5 num-tx-queues 6
num-rx-desc 4096 num-tx-desc 4096
rss { ipv4 ipv4-udp ipv4-tcp } }
dev 0000:47:00.0 { ... same ... } }
Receive-queue placement — one queue per worker, both interfaces, no sharing:
| Worker | lcore | Access queue | Uplink queue |
|---|---|---|---|
vpp_wk_0 |
2 | 0 | 0 |
vpp_wk_1 |
3 | 1 | 1 |
vpp_wk_2 |
4 | 2 | 2 |
vpp_wk_3 |
5 | 3 | 3 |
vpp_wk_4 |
6 | 4 | 4 |
The statistics segment is sized to 1024 MB. VPP's 32 MB default is exhausted
well before this scale, because the BNG allocates a forwarding entry and
per-session counters for every subscriber.
3.4 Service configuration
| Subscriber pool | 100.64.0.0/17 (32,766 usable) |
| Access interface | FortyGigabitEthernet1/0/0 |
| Uplink interface | FortyGigabitEthernet47/0/0 |
| AAA mode | open admission (local AAA measured separately in §5.8) |
| Captive portal | 100.64.0.1 |
| Plan under test | Bronze — 20/25 Mbps down (CIR/PIR), 10/12 Mbps up |
| DHCP relay | giaddr block of 64, 100.64.127.1 upward |
3.5 Licence state, verified at launch
The session cap is a property of the licence, not the platform, so the gate
records it before the run starts:
licence VALID grant bng.max_sessions = 25000
cap 25000 0 sessions resident
A reader may notice the platform reports max_source: free_baseline even when
fully licensed. The number is correct; that provenance label is wrong
upstream and is being tracked. The cap in force during this run was 25,000,
and the working set was 5,000 — so no result here is cap-constrained.
3.6 Load generation
| Generators | 2 hosts (bluedot2, bluedot3) |
| Simulator | CPESIM 0.4.17 |
Both generator hosts are wired symmetrically with a port on each side of the
BNG, and each carries two roles:
| Host | Role | Interface | PCI bus | Address |
|---|---|---|---|---|
bluedot2 |
CPE generator (access side) | enp1s0f0 |
01:00.0 |
L2 only, no address |
bluedot2 |
Uplink origin (core side) | enp71s0f0 |
47:00.0 |
10.0.0.3/24 |
bluedot3 |
CPE generator (access side) | enp1s0f0 |
01:00.0 |
L2 only, no address |
bluedot3 |
Uplink origin (core side) | enp71s0f0 |
47:00.0 |
10.0.0.2/24 |
Both origins hold a return route 100.64.0.0/17 via 10.0.0.1 so downstream
traffic reaches the subscriber pool. This run used both hosts for CPE
generation, with bluedot3 as the active uplink origin (10.0.0.2).
The access-side interfaces carry no IP address: the simulator drives raw frames
on them, relaying DHCP with a source giaddr, so there is nothing for the host
kernel to address. The PCI buses above are derived from the predictable
interface names (enp71s0f0 → bus 0x47) and place the generator ports in the
same slots as the platform's own, these being identically-specified chassis.
On the generator NIC chips. The generators were not read with
dpdk-devbind during this run, so their controllers are not confirmed
first-hand here. The evidence that they match the platform is strong but
indirect: all three chassis enumerate the same PCI topology — a 40GbE port at
bus 01:00.0, a second at 0x47, and an Intel I350 pair at bus 0x4a (idle on
the box under test, and the management port on bluedot3). Identical
slot-for-slot enumeration across three machines indicates identically-specified
chassis,
which would put Intel XL710 backplane controllers in the generators too.
Treated as inference, not measurement, and flagged for first-hand confirmation
on the next rig session.
It does not weaken the report, because generator capability here is established
by measurement rather than part number: the ceilings in §5.7 are ~20 Gbps
aggregate, 15.2 Mpps at 128B and 21.93 Mpps at 64B, each held byte-identical
across five different platform configurations. A part number would explain those
ceilings; it would not change them, and it is the measured ceiling that makes
the generator-limited cells floors.
The generators bound most forwarding cells, but not all in the same way.
Of the 20 UDP cells, 4 found a platform ceiling, 13 reached line rate with zero
loss, and 3 are floors where the rig under-offered. The distinction matters:
only the floors understate the platform. §5.7 separates them, and the rig's
~20 Gbps aggregate ceiling is what makes the large-frame cells wire-speed
results rather than shortfalls.