OPNsenseVI · Hardware and Virtualisation DesignHardware and virtualisation design
Offload — checksum, TSO, LRO, RSS — and what to disable for capture/IDS
What you'll learn
- Explain what checksum offload, TSO, LRO and RSS do
- Identify which offloads to leave enabled and which to disable
- Disable offloads that interfere with Suricata and tcpdump
- Read NIC offload state from ifconfig and sysctl
Prerequisites
Verified against OPNsense 25.x · FreeBSD 14.x · PF (FreeBSD packet filter) FreeBSD 14.x · Unbound 1.20+ · Kea DHCP OPNsense 25.x plugin · WireGuard in-kernel + OPNsense plugin · strongSwan (IPsec plugin) OPNsense 25.x plugin · OpenVPN 2.6.x · Suricata 7.x · 2026-08-14
Modern NICs do a lot of work that used to be the kernel’s job: computing IP and TCP checksums, splitting large TCP segments into wire-sized chunks, merging small segments into larger ones, and distributing packets across CPU cores. These offloads are why a single 2 GHz core can forward 1 Gbit/s. They are also the reason a packet capture or an IDS sees “wrong” packets — and the reason a misconfigured offload can introduce subtle bugs. This lesson covers what each offload does, why they are usually enabled, and which must be disabled for packet capture, IDS, or VPN workloads.
The four offloads the firewall operator touches
Four offloads are exposed in ifconfig output and tunable per
NIC:
| Offload | What it does | Default | When to disable |
|---|---|---|---|
| Checksum offload (rx-csum, tx-csum) | The NIC computes IP and TCP/UDP checksums on transmit, validates them on receive. | On | Rarely. Disable only on broken NICs that compute wrong checksums. |
| TSO (TCP Segmentation Offload) | The kernel hands the NIC a large TCP segment (up to 64 KB); the NIC splits it into wire-sized (1500-byte) segments on transmit. | On | When packet capture sees segments > MTU, or when Suricata must see every wire-sized packet. |
| LRO (Large Receive Offload) | The NIC merges multiple small received TCP segments into one large segment before delivering to the kernel. | On | When Suricata, netflow, or packet capture must see every wire-sized segment. |
| RSS (Receive Side Scaling) | The NIC distributes received packets across multiple CPU queues based on a hash. | On | Never. RSS is purely beneficial on multi-core systems. |
There are other offloads (LSO, UFO, RSS hash type), but the four above are the ones the operator actually configures.
$ ifconfig igb0igb0: flags=8863<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=4e527bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,WOL_UCAST,WOL_MCAST,WOL_MAGIC,VLAN_HWTSO,NETIF_TSO6,LRO6>
ether a4:5e:60:dd:ee:ff
inet 192.0.2.1 netmask 0xffffff00 broadcast 192.0.2.255
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
media: Ethernet autoselect (1000baseT <full-duplex>)
status: active
hwassist: csumb_tx=0xfffff,csumb_rx=0xfffff,scumb_tx=0,scumb_rx=0Illustrative output
Why these offloads are usually enabled
The four offloads exist because they make forwarding faster. The savings are large:
- Checksum offload: the NIC computes a checksum in dedicated hardware at line rate. The kernel would otherwise compute it per packet, spending CPU cycles on arithmetic that touches every byte of the payload.
- TSO: the kernel hands the NIC a 64 KB TCP segment. Without TSO, the kernel must split it into 46 1500-byte segments, each with its own IP and TCP header, each with its own checksum. With TSO, the NIC does this splitting in hardware at line rate.
- LRO: the NIC merges incoming small segments into one large buffer. Without LRO, the kernel must reassemble every small segment even when the application is going to read the bytes into one big buffer anyway.
- RSS: the NIC distributes packets across cores. Without RSS, one core does all the work.
The CPU savings are an order of magnitude on heavy flows. The firewall that turns these off pays for it in throughput.
When to disable offloads
Three workloads require disabling some offloads:
Packet capture with tcpdump
When the operator runs tcpdump -nei igb0, the kernel hands
the packet to BPF (or pcap on newer systems) before it
reassembles. With TSO enabled on the transmit side, the
captured outbound packet is the large pre-segment buffer, not
the wire-sized segments. With LRO enabled on the receive
side, multiple small segments are merged into one before the
kernel sees them.
For capture of outbound traffic, disable TX-side TSO:
ifconfig igb0 -tso. For capture of inbound traffic, disable
RX-side LRO: ifconfig igb0 -lro. The capture will then show
every wire-sized segment.
Suricata IDS
Suricata operates on individual packets for stateful inspection. LRO-merged segments confuse the stream engine (Suricata expects to see segments in order; LRO delivers them out of order in some configurations). Disable LRO on any interface Suricata monitors:
ifconfig igb0 -lro
Make this persistent via System → Advanced → Networking → LRO offload in the OPNsense GUI, or by adding the sysctl to
the tunables.
IPsec / WireGuard with hardware offload
Some IPsec configurations interact badly with TSO when the encrypt-then-segment sequence is unclear to the kernel. Disable TSO on the IPsec tunnel interface and on the underlying physical NIC if the encrypted tunnel drops segments or shows checksum errors.
How to read and set offload state
ifconfig <ifname> shows current offload state in the
options= line. To toggle:
ifconfig igb0 -tso # disable TSO on igb0
ifconfig igb0 tso # enable TSO on igb0
ifconfig igb0 -lro # disable LRO on igb0
ifconfig igb0 -txcsum # disable TX checksum offload
These are runtime changes; they do not persist across reboot.
To make persistent, add to System → Advanced → System Tunables
in OPNsense. The tunables are:
hw.igb.tso(or per-interface equivalent) controls TSO on igb NICs.net.inet.tcp.tsocontrols kernel TSO globally.
For most firewalls, leaving TSO and LRO enabled is correct. The operator’s job is to know what to turn off and when.
RSS configuration
RSS is controlled per-NIC. On Intel igb:
sysctl dev.igb.0.num_queues
sysctl dev.igb.0.queue0.intr_rate
To change the number of queues, set the loader tunable
hw.igb.max_interrupt_rate or use the ifconfig igb0 rxcsum
flags. The right number of queues equals the number of CPU cores
that can be productively used for receive processing; for a
4-core box, 4 queues.
Production patterns
Three patterns cover most decisions:
- For forwarding gateways: leave all offloads at defaults. RSS distributes load; TSO/LRO/checksum offload reduce CPU.
- For Suricata IDS sensors: disable LRO on every monitored interface. Leave TSO enabled (Suricata’s stream engine handles TSO correctly on modern FreeBSD).
- For packet capture workstations: temporarily disable TSO and LRO on the capture NIC while capturing; re-enable after.
Summary
- Four offloads matter: checksum, TSO, LRO, RSS. Leave them enabled by default; they exist because they make forwarding fast.
- TSO and LRO must be disabled for IDS sensors and packet capture, because they hide the wire-sized segments.
- Disabling TSO or LRO globally is almost always wrong. Do it per-interface and document the change.
- RSS is purely beneficial; never disable it on multi-core.
Knowledge check · 4 questions
Q1. You are setting up Suricata on an OPNsense firewall for in-line IDS. Which offload must you disable and why?
Q2. RSS (Receive Side Scaling) distributes received packets across CPU cores based on a hash, and should be enabled on multi-core systems.
Q3. Which of the following are valid reasons to disable NIC offloads? Select all that apply.
Q4. You disabled net.inet.tcp.tso=0 globally on a 1 GbE forwarding firewall to debug a Suricata issue. Suricata has been moved to a separate interface. The forwarding throughput has dropped from 940 Mbit/s to 250 Mbit/s. What is the most likely cause and fix?
Passing score: 75%. Answers are checked in this browser.