Alternate TCP Stacks
Load the optional RACK and BBR TCP stacks in FreeCORE 15.1 and select one inside a VNET jail.
FreeCORE 15.1 ships the FreeBSD RACK and BBR TCP stacks as loadable kernel modules. They exist for workloads that move data over lossy, high-latency internet paths, where the default loss-based congestion control leaves throughput unused.
Nothing is loaded by default. On a system that does not opt in, the modules are files on disk and change no behavior.
tcp_rack.ko— the RACK stack. The supported opt-in.tcp_bbr.ko— BBR. Ships for experimentation only. See the warning below.tcphpts.ko— the high-precision timer system both stacks require. It is not selectable itself.
Confirm the default state
On a system that has not opted in, only the default stack is present:
sysctl net.inet.tcp.functions_available
Stack D Alias PCB count
freebsd * freebsd 20
sysctl net.inet.tcp.functions_default
net.inet.tcp.functions_default: freebsd
Load a stack
Try a stack for the current boot only:
kldload tcp_rack
tcphpts loads automatically as a dependency; loading it separately is not
needed. rack then appears in net.inet.tcp.functions_available, and the
default stack is still freebsd — loading a module makes a stack available,
it does not select it.
To load a stack at every boot, go to System > Tunables, click ADD, set
Variable to tcp_rack_load, Value to YES, and Type to loader,
then reboot. Add tcp_bbr_load the same way for BBR. This boot-time form, and
the jail's /etc/sysctl.conf below, are the standard FreeBSD mechanisms;
FreeCORE tests loading and selecting a stack at run time.
Select a stack for one jail
The stack a connection uses is chosen per network stack, so a jail can select its own only when it has its own network stack — that is, a VNET jail.
Inside the VNET jail:
sysctl net.inet.tcp.functions_default=rack
To make it persistent, put net.inet.tcp.functions_default=rack in the jail's
/etc/sysctl.conf.
The host and every other jail keep their own default. A shared-IP jail cannot do this and the write is refused:
sysctl net.inet.tcp.functions_default=rack
sysctl: net.inet.tcp.functions_default=rack: Operation not permitted
That refusal is correct: a shared-IP jail does not own the stack it is using, so the setting is not the jail's to change.
Things to know before switching
tcphpts cannot be unloaded. Unloading a stack module works —
kldunload tcp_rack succeeds and rack disappears from the available list — but
tcphpts then refuses:
kldunload tcphpts
kldunload: can't unload file: Device busy
This is deliberate upstream behavior, not a fault: a stack's function pointers cannot be retired safely, so only a forced unload is permitted. Treat loading HPTS as a decision that lasts until the next reboot. A reboot returns the system to the default stack with nothing loaded.
Loading HPTS is not free. It allocates a per-CPU timer entry and registers a software interrupt and callout on every CPU. That is the reason to leave it unloaded unless a workload needs it.
Pacing is software only. The FreeCORE kernel does not enable RATELIMIT, so
neither stack uses NIC hardware pacing.
Appliance services stay on the default stack. NFS, iSCSI and SMB continue to
use freebsd. An alternate stack is an administrator's choice for a specific
workload, not a system-wide setting to change casually.
Support
RACK is the supported opt-in.
BBR is unsupported and unvalidated for behavior. FreeBSD implements BBRv1, which upstream has not changed as BBR since January 2025, and BBRv1 is known to compete aggressively against loss-based flows and to raise retransmission rates on shallow-buffered paths — including a shared household uplink. It is shipped so that administrators who want to experiment do not have to build and load their own kernel modules against a FreeCORE kernel, which nothing tests. FreeCORE verifies that the module is present, loads, and can be selected in a VNET jail. It makes no claim about its throughput or its fairness.
Selecting an alternate stack is outside default support either way. If a problem
appears, reproduce it on the freebsd stack before reporting it.