Project

General

Profile

Actions

Bug #9414

open
JS

Persistent Netmap POLLERR on recreated PPPoE interface causes CPU-intensive busy loop, massive log growth and unresponsive shutdown

Bug #9414: Persistent Netmap POLLERR on recreated PPPoE interface causes CPU-intensive busy loop, massive log growth and unresponsive shutdown

Added by Julian Schaufel about 5 hours ago. Updated about 4 hours ago.

Status:
New
Priority:
Normal
Assignee:
-
Target version:
Affected Versions:
Effort:
high
Difficulty:
Label:

Description

Persistent Netmap POLLERR on recreated PPPoE interface causes CPU-intensive busy loop, massive log growth and unresponsive shutdown

1. Summary

I am experiencing a reproducible problem with Suricata running in Netmap IPS mode on OPNsense after a scheduled WAN interface reset.

Whenever the PPPoE WAN interface is disconnected and recreated, Suricata starts reporting the following errors continuously:

pppoe0: error reading netmap data via polling: No buffer space available
pppoe0^: error reading netmap data via polling: No buffer space available

The errors are repeated at a very high rate. The two affected Suricata capture threads consume approximately 1.4 CPU cores combined.

In addition, Suricata cannot be stopped or restarted cleanly afterwards. The OPNsense service restart operation remains stuck waiting for the existing Suricata process to exit.

The error also causes an enormous amount of log data to be generated. Individual daily Suricata log files reach several hundred gigabytes in logical size, consuming tens of gigabytes of actual ZFS storage despite LZ4 compression.

I suspect that a persistent `POLLERR` condition in the Netmap capture loop is not handled appropriately. The problem may be triggered by the destruction and recreation of the virtual PPPoE interface under FreeBSD.

I would appreciate an investigation of both the underlying Netmap error handling and the possibility of providing a reliable recovery mechanism.

2. System environment

- Firewall platform: OPNsense 26.7.8
- Operating system: FreeBSD 15.1-RELEASE-p6
- Architecture: amd64
- CPU: Intel N355, 8 cores / 8 threads
- RAM: 16 GB
- Storage: 1 TB NVMe SSD
- Network controller: Intel I226-V (`igc0`)
- Suricata package: `opnsense/suricata` 8.0.8
- Package repository: OPNsense repository (binary package)
- Suricata build: RELEASE
- Netmap support: enabled (v14+)
- Hyperscan: enabled
- IPFW support: enabled
- SIMD support: SSE2

The Suricata package was installed on October 31, 2026.

The binary is a stripped release build without local debugging symbols.

3. Network topology

The WAN connection is configured as follows:

Intel I226-V (igc0)
        |
        +-- VLAN 7 (vlan0.1)
                 |
                 +-- PPPoE (pppoe0)

The PPPoE interface has an MTU of 1484.

Suricata monitors the WAN interface `pppoe0` in Netmap IPS mode.

The generated Suricata Netmap configuration contains:

netmap:
  - interface: default
    threads: auto
    copy-mode: ips
    disable-promisc: no
    checksum-checks: auto

  - interface: pppoe0
    copy-iface: pppoe0^

  - interface: pppoe0^
    copy-iface: pppoe0

This configuration is generated by OPNsense.

4. Trigger and reproduction

The problem is triggered by the OPNsense Cron job named "Periodic interface reset".

The job runs at 04:00 on days 4, 8, 12, 16, 20, 24 and 28 of each month.

It executes:

configctl interface reconfigure wan

This is a complete WAN interface reconfiguration, including tearing down and recreating the PPPoE session.

I first noticed this issue around late August / early September this year.

The issue started occurring after I changed my OPNsense setup from scheduled full system reboots to scheduled interface resets, which are used to obtain a new public IP address.

Since making this change, Suricata has occasionally stopped working or encountered problems involving the Netmap interface in my PPPoE setup.

I cannot confirm that the interface resets are the direct cause of the issue. However, the timing strongly suggests a possible connection between the interface reset procedure and the Suricata/Netmap problem.

Two confirmed examples:

November 4, 2026

The system log shows the following sequence:

- 04:00:00: `ppp-linkdown` on `pppoe0`
- 04:00:00: Removing the IPv4 address fails with `Can't assign requested address`
- 04:00:02: The existing `pppoe0` interface is removed and a new Netgraph interface `ng0` is created.
- 04:00:02: The kernel renames `ng0` back to `pppoe0`.
- 04:00:03: `ppp-linkup` on `pppoe0`
- 04:00:03: A new public IPv4 address is assigned.

The Netmap polling errors occur after this interface recreation.

November 8, 2026

The same scheduled interface reset ran again at 04:00. The Netmap errors appeared again and were still occurring later that day.

This makes the relationship between PPPoE interface recreation and the Suricata error reproducible.

5. Netmap errors and network impact

Suricata continuously logs:

pppoe0: error reading netmap data via polling: No buffer space available
pppoe0^: error reading netmap data via polling: No buffer space available

Many identical messages appear within the same second.

Despite these messages, the PPPoE connection is successfully established and normal Internet connectivity remains available without noticeable performance problems.

A 30-second interface counter measurement showed:

Interface Received packets during interval Ierrs / Idrop Oerrs / Drop
pppoe0 +9,584 0 0
igc0 +9,548 0 0

These counters do not show errors or drops in the normal interface data path during that interval. They do not, however, prove that Suricata's IPS inspection remains fully functional.

The Netmap-related counters also increased during one 30-second measurement:

dev.netmap.iflib_rx_miss:
619136 -> 619156

dev.netmap.iflib_rx_miss_bufs:
658582 -> 658602

The significance of these counter increases is currently unclear.

6. CPU consumption

Using FreeBSD `top` in per-thread mode, I measured the CPU consumption of the two affected Suricata workers.

Example output:

103226 suricata{W#01-pppoe0^}  72.22%
103219 suricata{W#01-pppoe0}   71.29%

103226 suricata{W#01-pppoe0^}  72.83%
103219 suricata{W#01-pppoe0}   72.13%

The two threads therefore consume approximately 1.4 fully utilized CPU cores combined.

This CPU consumption occurs while the repeated Netmap polling errors are being logged.

The affected threads are:

- `W#01-pppoe0`
- `W#01-pppoe0^`

7. Source code observation

I inspected the Netmap capture code in `src/source-netmap.c` from the Suricata 8.0.8 source tree:

https://github.com/OISF/suricata/blob/suricata-8.0.8/src/source-netmap.c

In the polling loop, the code handles `POLLERR` by logging an error and then immediately continuing with the next iteration.

The relevant logic is:

if (unlikely(fds.revents & POLL_EVENTS)) {
    if (fds.revents & POLLERR) {
        SCLogError("%s: error reading netmap data via polling: %s",
                   ntv->ifsrc->ifname, strerror(errno));
    } else if (fds.revents & POLLNVAL) {
        SCLogError("%s: invalid polling request", ntv->ifsrc->ifname);
    }
    continue;
}

There does not appear to be a delay, rate limiting mechanism, or recovery attempt in this error branch.

This appears consistent with the observed CPU-intensive busy loop.

I also wonder whether `errno` is necessarily meaningful in this case: the branch is entered because `poll()` reports `POLLERR` in `revents`, not necessarily because `poll()` itself returned an error. Could the displayed `No buffer space available` message therefore be misleading or reflect a stale `errno` value?

8. Suricata shutdown and restart problem

After the Netmap errors begin, Suricata cannot be restarted through the normal OPNsense service mechanism.

The following command does not complete successfully:

configctl ids restart

The running Suricata process remains alive, and the restart operation waits indefinitely for it to exit.

During one investigation, the process was:

PID: 29471
Command:
/usr/local/bin/suricata -D --netmap \
  --pidfile /var/run/suricata.pid \
  -c /usr/local/etc/suricata/suricata.yaml

The process had been running since November 1, 2026, at approximately 04:01:28.

Multiple stop and restart attempts remained waiting for the same PID, for example:

pwait -op 29471

The OPNsense service script uses the default `SIGTERM` signal and then calls `wait_for_pids`. The FreeBSD `rc.subr` implementation repeatedly waits using `pwait` while the process exists. There is no timeout or automatic fallback to `SIGKILL` in this function.

The process continues to hold four open `/dev/netmap` file descriptors (FD 6-9).

Kernel thread inspection

`procstat -kk` showed the two Netmap workers remaining active or waiting on synchronization operations.

LLDB backtrace

I attached LLDB to the running process and executed:

thread backtrace all

The backtrace of `W#01-pppoe0` showed:

_pthread_mutex_lock
syslog
SCLogMessage
SCLogErr
[Suricata internal function]
[Suricata internal function]

The backtrace of `W#01-pppoe0^` showed:

sysctl
gethostname
syslog
SCLogMessage
SCLogErr
[Suricata internal function]
[Suricata internal function]

The main thread was in:

__usleep
DetectEngineReload
SuricataMainLoop

The binary is stripped, so the internal Suricata function names could not be resolved completely.

These snapshots show that both capture workers were inside the error logging path at the time of inspection. A permanent mutex deadlock has not been conclusively established.

9. ZFS ARC memory usage

I also observed a significant increase in ZFS ARC memory usage whenever the Netmap error condition is active.

The ARC is normally comparatively small on this system, but grows to approximately half of the total physical RAM during the error condition.

Example measurement on November 8, 2026:

kstat.zfs.misc.arcstats.size:
8517452056

kstat.zfs.misc.arcstats.data_size:
7844398592

kstat.zfs.misc.arcstats.metadata_size:
331061760

kstat.zfs.misc.arcstats.c_max:
15776538624

vfs.zfs.arc.max:
0

This corresponds to approximately 8.5 GB of ARC usage on a system with 16 GB RAM.

Most of the ARC consists of data rather than metadata.

I cannot currently prove that this increase is directly caused by Suricata. However, it correlates with the period of intensive log generation and may be related to the additional filesystem activity.

10. Massive log generation and disk usage

The repeated Netmap errors generate an exceptionally large amount of Suricata log data.

The logs are stored under `/var/log/suricata/`.

The `/var/log` directory is mounted on the ZFS dataset `zroot/var/log`, not on a RAM disk.

Examples of daily Suricata log sizes:

Log file Logical file size Allocated size reported by `du`
suricata_20261104.log 641 GB Not measured
suricata_20261105.log 769 GB Not measured
suricata_20261106.log 766 GB 48 GB
suricata_20261107.log 687 GB 43 GB
suricata_20261108.log 558 GB (at 21:28) 35 GB

The ZFS dataset uses LZ4 compression:

compression: lz4
compressratio: 15.95x
used: 419G
logicalused: 6.50T
available: 470G

The dataset statistics include other log files as well, not only Suricata.

Although compression is very effective, the Suricata logs still consume tens of gigabytes of actual filesystem space per day.

This represents substantial additional storage usage and filesystem activity.

11. Current understanding and questions

My current understanding is that a persistent `POLLERR` condition occurs after the PPPoE interface is destroyed and recreated.

Suricata then appears to repeatedly log the error and immediately retry polling, resulting in:

- High CPU consumption by both Netmap workers.
- Very large quantities of repetitive log output.
- Increased ZFS ARC usage that correlates with the error state.
- A Suricata process that does not terminate through the normal service restart mechanism.

I would appreciate your assessment of the following questions:

1. Is a persistent `POLLERR` condition on a Netmap interface a known issue on FreeBSD?
2. Is the immediate retry after `POLLERR` intentional, even if the condition persists indefinitely?
3. Should this error path include a delay, backoff, or rate limiting of identical log messages?
4. Could repeated calls to `SCLogError()` from multiple capture workers contribute to the observed mutex contention or shutdown problem?
5. Could this behavior be related to the destruction and recreation of a virtual PPPoE interface?
6. Is there a supported way to reinitialize the Netmap adapter after the underlying interface has been recreated?
7. Can the capture worker or the affected Netmap interface be restarted safely when this condition is detected?

12. Requested recovery mechanism / acceptable short-term solution

I understand that the underlying cause may be related to a FreeBSD or Netmap limitation involving PPPoE interfaces and may not be straightforward to fix entirely within Suricata.

However, a complete fix for the underlying interface problem is not my only acceptable outcome.

As a first step, I would already consider a reliable recovery mechanism a very useful improvement.

For example, Suricata could:

- Detect a persistent, unrecoverable `POLLERR` condition.
- Stop and recreate the affected capture worker.
- Close and reopen the affected Netmap adapter, if this is safe and supported.
- If worker-level recovery is not possible, initiate or expose a controlled IDS/IPS restart mechanism.
- Use a bounded retry strategy with delays to prevent endless restart loops.
- Limit repeated identical log messages to avoid excessive CPU, storage and I/O consumption.
- Report clearly whether recovery succeeded or whether IPS inspection remains impaired.

My main concern is that a single interface recreation should not leave Suricata in a state where it continuously consumes CPU resources, generates hundreds of gigabytes of logical log data per day, and cannot be restarted cleanly.

Even a reliable way to recover IPS operation after such an error would be a valuable short-term solution, while the underlying cause is investigated.

Thank you for your time and for looking into this issue.

I can provide additional logs, kernel stack traces, LLDB output, configuration files and further reproduction data if required.


Files

02-netmap-config.txt (335 Bytes) 02-netmap-config.txt Julian Schaufel, 11/08/2026 10:06 PM
01-build-info.txt (4.22 KB) 01-build-info.txt Julian Schaufel, 11/08/2026 10:06 PM
04-suricata-error-tail.txt (18.8 KB) 04-suricata-error-tail.txt Julian Schaufel, 11/08/2026 10:06 PM
05-runtime-diagnostics.txt (7.67 KB) 05-runtime-diagnostics.txt Julian Schaufel, 11/08/2026 10:06 PM
06-lldb-backtrace.txt (5.82 KB) 06-lldb-backtrace.txt Julian Schaufel, 11/08/2026 10:06 PM
03-system-pppoe-reset.txt (70.3 KB) 03-system-pppoe-reset.txt Julian Schaufel, 11/08/2026 10:43 PM

JS Updated by Julian Schaufel about 5 hours ago Actions #2

  • File deleted (03-system-pppoe-reset.txt)

JS Updated by Julian Schaufel about 4 hours ago Actions #3

  • Effort changed from medium to high
Actions

Also available in: PDF Atom