Request a larger receive buffer for conntrack events - #314
Merged
Conversation
hiroTamada
marked this pull request as ready for review
July 27, 2026 19:54
The conntrack event socket ran on the kernel default. Production hosts report "recv conntrack events: no buffer space available" roughly once a minute each, and every one of those is a batch of connection events the auto-standby controller never sees. A connection whose event is lost is not counted as inbound activity, so an instance still serving it looks idle. Request 40MiB, which Linux stores as 80MiB, against a net.core.rmem_default of 8MiB on those hosts. SO_RCVBUFFORCE first so the value cannot be silently clamped to net.core.rmem_max, falling back to SO_RCVBUF where CAP_NET_ADMIN is unavailable. Both failing is tolerated: a socket with the default buffer still delivers events, so sizing must not stop the subscription from opening. This reduces how often events are dropped. It does not make a drop recoverable, and it does not make the idle decision verify itself. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
hiroTamada
force-pushed
the
hypeship/auto-standby-survive-conntrack-drops
branch
from
July 27, 2026 19:57
b877dca to
813918d
Compare
hiroTamada
marked this pull request as draft
July 27, 2026 19:57
hiroTamada
marked this pull request as ready for review
July 27, 2026 19:59
sjmiller609
approved these changes
Jul 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The conntrack event socket ran on the kernel default receive buffer. On production hypeman hosts the kernel reports
recv conntrack events: no buffer space availableroughly once a minute each — 345 times across three hosts in a 4.5 hour window:Every one of those is a batch of connection events the auto-standby controller never sees. The tracked connection view is built from that stream, so a connection whose event is lost is not counted as inbound activity — and an instance still serving it looks idle. Since a suspended guest is only woken by a new connection, the already-open one then hangs until the client gives up.
Change
Request 40MiB for the socket, which Linux stores as 80MiB (it allocates twice what you ask for).
net.core.rmem_defaulton these hosts is 8MiB, so this is roughly 10× the headroom.SO_RCVBUFFORCEis tried first because it ignoresnet.core.rmem_maxand so cannot be silently clamped; it needsCAP_NET_ADMIN, which hypeman has (runs as root withcap_net_adminin the unit's bounding set). Falls back toSO_RCVBUFwhere that capability isn't available. Both failing is tolerated — a socket with the default buffer still delivers events, so buffer sizing must not stop the subscription from opening.What this does and does not do
It reduces how often events are dropped. That's the whole claim.
It does not make a drop recoverable. On
ENOBUFSthe reader still treats it as a stream failure and tears the subscription down, which loses everything else that arrives during the reconnect, and nothing re-reads the connection table on the way back up. And it does not make the idle decision verify itself —executeStandbystill trusts the event-derived view without confirming it against the host table before suspending a guest.Both of those are on
hypeship/auto-standby-conntrack-resync-parkedandhypeship/auto-standby-hardening-parkedrespectively, deliberately kept out of this PR.There is also a reason the buffer overflows that more buffer cannot fix:
handleConnectionEventiterates every tracked instance under the global lock for every conntrack event on the host, so the consumer falls behind and the reader blocks. Indexing that lookup is the change that would attack the cause.Testing
go test -race ./lib/autostandby/...passes and the package builds for linux and darwin. No new tests: this is a socket option whose effect is a kernel-side buffer size, and asserting it would require a privileged netlink socket that CI doesn't have.The real verification is the drop rate in production. Run the query above before and after rollout, grouped by
host.name. If the rate doesn't fall materially, the buffer was not the binding constraint and the consumer-side fix is the next thing to try.Not included, and worth knowing: the socket is never read back with
getsockopt, so the effective buffer size isn't logged anywhere. The drop rate is the only feedback signal.🤖 Generated with Claude Code