fix(fc): slot-driven guest IPv6 config; default to IPv4-only to eliminate Happy Eyeballs latency - #3587
Open
AdaAibaby wants to merge 4 commits into
Open
fix(fc): slot-driven guest IPv6 config; default to IPv4-only to eliminate Happy Eyeballs latency#3587AdaAibaby wants to merge 4 commits into
AdaAibaby wants to merge 4 commits into
Conversation
…ency The tap interface is configured IPv4-only: process.go builds the ip= kernel parameter with NamespaceIP/TapIP/TapMask but no IPv6 router or prefix is advertised on the host side of the tap. With ipv6.disable=0 and ipv6.autoconf=1 the guest kernel enables SLAAC, which at best yields an unroutable fe80:: link-local address and at worst waits for an RA that never arrives. The practical consequence is a ~250 ms Happy Eyeballs penalty (RFC 8305) on every outbound connection to a dual-stack host: the kernel prefers the AAAA address, the attempt fails with EHOSTUNREACH or a silent NDP timeout, then falls back to IPv4. pip install, npm install, and any HTTP API call to a major service (OpenAI, GitHub, PyPI, GCP) all have AAAA records, so every sandbox pays this cost on every first TCP connection per destination. Fix: set ipv6.disable=1 and drop the now-redundant ipv6.autoconf=1. This is a one-line kernel cmdline change with no other code impact. Full IPv6 support can be re-enabled once the host networking layer gains a complete stack (RA, prefix delegation, ip6tables). Fixes: e2b-dev#3585
AdaAibaby
requested review from
ValentaTomas,
dobrac and
jakubno
as code owners
August 18, 2026 06:30
Previously the guest kernel always booted with ipv6.disable=1 (hardcoded in kernel_args.go). This fix keeps the same safe default while making the flag slot-driven, so the codebase is ready for a future host-side IPv6 stack without a scattered search-and-replace. Changes: - Slot.HasIPv6Router() bool — the single source of truth for whether the host tap has an IPv6 router configured. Returns false today (no RA on the tap); flip to true (or derive from real IPv6 state) when the host gains IPv6. - ProcessOptions.IPv6RouterConfigured bool — carries the slot's answer into buildKernelArgs without coupling kernel_args.go to the network package. Set from Slot.HasIPv6Router() in Process.Create, one line before the call. - buildKernelArgs selects ipv6.disable=0 or =1 based on the flag instead of a string literal. The default (false) preserves the existing behaviour: guests without an IPv6 router on the host tap boot with ipv6.disable=1. - kernel_args_test.go adds an "ipv6 router configured" case that asserts ipv6.disable=0 when IPv6RouterConfigured=true. Fixes e2b-dev#3585.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 926e6ed210
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
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.
Fixes #3585.
Problem
kernel_args.gohardcodedipv6.disable=0andipv6.autoconf=1, enabling IPv6 inside every Firecracker guest. However the host-side network setup only configures IPv4 — no router advertisement is sent on the host tap interface, so SLAAC produces only an unroutablefe80::link-local address.With IPv6 nominally enabled but unroutable, the Linux kernel's address selection (RFC 6724) prefers AAAA records. On every outbound connection to a dual-stack host the kernel tries IPv6 first, hits EHOSTUNREACH or waits for a silent NDP timeout, then falls back to IPv4
under the Happy Eyeballs ~250 ms delay (RFC 8305).
Every sandbox is affected. pip, npm, cargo, apt, and any HTTP API call to a major service (OpenAI, GitHub, PyPI, GCP, AWS) has AAAA records. A package install that opens 20 TCP connections silently loses 5+ seconds.
Fix
Rather than hardcoding
ipv6.disable=1, the guest's IPv6 state is now derived from whether the host slot actually has an IPv6 router configured:Slot.HasIPv6Router() bool— single source of truth. Returnsfalsetoday (no RA on the tap); flip totrue(or read from real IPv6 slot state) when the host gains a full IPv6 stack.ProcessOptions.IPv6RouterConfigured bool— carries the slot's answer intobuildKernelArgswithout coupling the kernel-args layer to the network package. Set fromSlot.HasIPv6Router()inProcess.Create.buildKernelArgs— selectsipv6.disable=0or=1based on the flag. The zero-value default (false) preserves safe behavior: guests without an IPv6 router boot IPv4-only.This means today's sandboxes get
ipv6.disable=1(fixing the Happy Eyeballs regression), and future dual-stack support requires only flippingHasIPv6Router()— no scattered code changes.Changes
network/slot.goHasIPv6Router() bool— documented extension point, returnsfalsefc/process.goProcessOptions.IPv6RouterConfigured; set fromslot.HasIPv6Router()beforebuildKernelArgsfc/kernel_args.goipv6.disablederived fromoptions.IPv6RouterConfiguredinstead of hardcodedfc/kernel_args_test.goipv6.disable=1); addedipv6 router configuredcase (expectipv6.disable=0)docs/ARCHITECTURE.md