Skip to content

Add IPv6 support for slirp/rootless networking#212

Closed
ejc3 wants to merge 8 commits intomainfrom
work-from-main
Closed

Add IPv6 support for slirp/rootless networking#212
ejc3 wants to merge 8 commits intomainfrom
work-from-main

Conversation

@ejc3
Copy link
Copy Markdown
Owner

@ejc3 ejc3 commented Feb 3, 2026

Summary

Adds IPv6 support to rootless (slirp4netns) networking mode. VMs now get both IPv4 and IPv6 connectivity when the host has a global IPv6 address.

Changes

  • IPv6 network setup in namespace:

    • Guest VM: fd00:1::2/64
    • Gateway (tap0): fd00:1::1/64
    • IPv6 forwarding and NAT66 enabled between tap0 and slirp0
    • --enable-ipv6 and --outbound-addr6 flags passed to slirp4netns
  • fc-agent IPv6 configuration:

    • Parses ipv6=<client>|<gateway> from kernel cmdline
    • Configures eth0 with IPv6 address and default route
  • Test improvements:

    • test_ipv6_connectivity_in_vm: Verifies guest IPv6 address and gateway reachability
    • test_ipv6_egress_to_host: Tests egress to host's global IPv6 address
    • Changed health check tests to use curl instead of wget (more reliable)
    • Dynamic port allocation for test HTTP servers

Test Results

make test-root FILTER=ipv6
Summary [ 8.805s] 2 tests run: 2 passed

make test (full suite)
Summary [273.272s] 286 tests run: 286 passed (5 flaky), 14 skipped

Test plan

  • IPv6 connectivity test passes (guest gets fd00:1::2, can ping fd00:1::1)
  • IPv6 egress test passes (VM reaches host's global IPv6)
  • Full test suite passes
  • libslirp 4.7+ detected (supports IPv6 DNS proxying)

@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 3, 2026

⚠️ CI Check Failed

The Host-Root-arm64-SnapshotEnabled check has failed. I cannot proceed with the review until CI passes.

Please check the failure at: https://github.com/ejc3/fcvm/actions/runs/21615706655/job/62293898577


Review by Claude | Run

@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 3, 2026

⚠️ CI Checks Failed

The following CI checks have failed:

I cannot proceed with the review until all CI checks pass. Please fix the failing tests before I can review the code.


Review by Claude | Run

@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 3, 2026

⚠️ Lint Failed

The Lint check has failed. I cannot proceed with the review until lint passes.

Please run the following locally to see and fix the issues:

cargo fmt --check
cargo clippy --all-targets -- -D warnings

Then fix the lint issues and push the changes.


Review by Claude | Run

@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 3, 2026

🔧 CI Auto-Fix

Created fix PR: #213

Issue: Port forward tests were flaky due to race condition between container-ready health check and nginx startup.

Fix: Added retry loops to give nginx time to bind to port 80 after container starts.

View Claude Run

@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 3, 2026

🔧 CI Auto-Fix

Created fix PR: #214

The lint job was failing due to an unused import (std::path::PathBuf) in src/network/pasta.rs. This has been removed in the fix PR.

View Claude Run

@ejc3 ejc3 changed the title Add IPv6 tests and fix health check default behavior Add IPv6 support for slirp/rootless networking Feb 3, 2026
@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 3, 2026

⛔ Lint Failed

The Lint check has failed on this PR. Please fix the linting issues before I can proceed with code review.

Check the lint failures here: https://github.com/ejc3/fcvm/actions/runs/21619566606/job/62305531034

Once lint passes, I'll automatically review the code.


Review by Claude | Run

@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 3, 2026

⚠️ CI Check Failed

The Host-Root-arm64-SnapshotDisabled check has failed. Please fix this before review can continue.

Failed Check:

Status:

  • ✅ Lint passed
  • ✅ Packaging passed
  • ❌ Host-Root-arm64-SnapshotDisabled failed
  • ⏳ Other checks still pending

Review by Claude | Run

@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 3, 2026

CI Failure Analysis

I analyzed CI #21619688864 but couldn't create an automatic fix.

Diagnosis

The CI is failing in 4 jobs with 2 distinct test failures:

Test Failures:

  1. test_dns_resolution_in_vm - Failed with error:

    • Error: OCI runtime error: crun: the requested cgroup controller \pids` is not available`
  2. test_port_forward_rootless - Failed with error:

    • bad request: add_hostfwd: slirp_add_hostfwd failed

Root Cause:
The primary issue is that the pids cgroup controller is not available in the GitHub Actions runner environment. This appears to be a cgroup v2 configuration issue on the ARM64 runners, where the pids controller is not properly enabled or mounted.

Why Not Fixable

This is an environmental/infrastructure issue, not a code issue:

  1. The missing pids cgroup controller is a system-level configuration problem on the GitHub Actions self-hosted runners
  2. The slirp4netns port forwarding failure is likely related to the same underlying cgroup/namespace issues
  3. This cannot be fixed with code changes - it requires:
    • Updating the runner system configuration to enable cgroup controllers properly
    • OR adding cgroup controller checks and graceful degradation in the test setup
    • OR skipping these specific tests when cgroup controllers are unavailable

Recommendation

The repository maintainers should either:

  1. Fix the GitHub Actions runner cgroup configuration to enable the pids controller
  2. Update the test setup to detect and skip tests that require unavailable cgroup controllers
  3. Investigate if this is a recent regression in the runner images

View Claude Run

ejc3 added 6 commits February 3, 2026 09:04
Add slirp_ipv6 test module with tests for:
- libslirp version detection (4.7+ supports native IPv6 DNS)
- DNS resolution in VMs
- IPv6 connectivity on eth0

Change health check default: don't auto-assign HTTP health check URL
from network config. HTTP health checks require an HTTP server in
the container. Use container-ready file mechanism by default instead.
Users can explicitly set --health-check for HTTP checks.

Also add find_available_port() helper to tests/common for port scanning.

Tested:
  make test-root FILTER=slirp_ipv6 - all 3 tests pass
  make test-root FILTER=sanity - sanity test still passes
- Switch from wget to curl for HTTPS testing (busybox wget doesn't
  properly support HTTPS through HTTP proxy)
- Use dynamic port allocation (find_available_high_port) instead of
  hardcoded 8080 to avoid conflicts with system services
- Add --vm flag to clone tests for nslookup/curl (run in VM, not container)
- Update test URLs: google.com → facebook.com, httpbin.org → checkip.amazonaws.com

Tests verified:
  test_egress_fresh_rootless - passed
  test_exec_rootless - passed
  test_port_forward_rootless - passed
test_ipv6_egress_to_host starts an IPv6-only server on host and
verifies VM cannot reach it. This documents that slirp4netns only
provides IPv4 NAT - IPv6 egress requires either:
  1. IPv6 NAT (not supported by slirp4netns)
  2. Bridged networking with IPv6 on the bridge
  3. A different networking solution like pasta
Enable IPv6 connectivity for VMs using slirp4netns:

- Add guest_ipv6 and host_ipv6 fields to NetworkConfig
- Configure IPv6 addresses on TAP devices (fd00:1::2/64 for guest)
- Enable IPv6 forwarding and NAT66 in namespace setup script
- Pass --enable-ipv6 and --outbound-addr6 to slirp4netns
- Detect host's global IPv6 address for outbound traffic
- Add configure_ipv6_from_cmdline() in fc-agent to parse ipv6= boot param
- Pass ipv6=<client>|<gateway> in kernel cmdline from podman.rs

Tested: make test FILTER=ipv6 - all 3 tests pass
- test_ipv6_connectivity_in_vm: ping to fd00::3 works
- test_ipv6_egress_to_host: VM reaches host's global IPv6
- test_ipv6_egress_internet: documents slirp4netns limitation
The test was checking for fd00::100 (namespace slirp0 address) but the
guest VM is configured with fd00:1::2. Also changed ping target from
fd00::3 (slirp DNS, unreachable without NAT66) to fd00:1::1 (gateway).

Tested: make test-root FILTER=ipv6 (2 tests pass)
@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 3, 2026

🔍 Claude Review

SEVERITY: low

Findings

[LOW] In test_slirp_ipv6.rs, the test test_ipv6_egress_to_host documents a limitation but doesn't actually test the expected failure case. The test currently accepts both success and failure outcomes (lines 329-346), which means it will always pass regardless of whether IPv6 egress works or not. Consider either:

  • Marking this test with #[should_panic] if IPv6 egress is expected to fail with current slirp4netns
  • Or split into two tests: one that verifies the limitation exists, and one that's marked as #[ignore] for when IPv6 NAT support is added

[LOW] In src/network/slirp.rs, the IPv6 detection logic in detect_host_ipv6() (lines 267-291) filters out ULA addresses starting with "fd" (line 283), but the function name and comment suggest it should detect global IPv6. The filter is too broad - it would incorrectly reject valid global addresses like fd42:: (ULA) while the intent is to filter ULA (fc00::/7). Consider changing line 283 to:

if \!addr.starts_with("fe80:") && \!addr.starts_with("fc") && \!addr.starts_with("fd")

Actually, this is already checking for "fd" prefix correctly, so this is fine. The current logic correctly filters both link-local (fe80::) and ULA (fc00::/7, which includes both fc and fd prefixes).

Summary

The IPv6 implementation is well-designed and comprehensive. The code quality is high with good error handling, clear documentation, and thorough testing. The only minor issues are in test design where one test doesn't properly validate failure modes.


Review by Claude | Run

The PR changed health checks from HTTP-based (which verified nginx was responding)
to container-ready file (which only verifies container started). This causes a race
condition where the container is marked healthy but nginx hasn't finished binding
to port 80 yet.

Add 30-second retry loops with 500ms intervals to both test_port_forward_bridged
and test_port_forward_rootless, giving nginx time to start after the container
becomes ready.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 3, 2026

⚠️ CI Check Failed

The Host-Root-arm64-SnapshotDisabled test has failed. I cannot proceed with the review until all CI checks pass.

Please fix the failing test before I can review this PR.

View failing test


Review by Claude | Run

Add Delegate=yes to fc-agent.service so podman can use cgroup
controllers (pids, memory, cpu) when running containers inside the VM.

Without this, crun fails with "the requested cgroup controller 'pids'
is not available" on fresh VM boots. Snapshot restores worked because
cgroups were already configured when the snapshot was taken.

Tested: FCVM_NO_SNAPSHOT=1 make test-root FILTER=test_dns_resolution_in_vm
@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 3, 2026

❌ CI Check Failed

The Host-Root-arm64-SnapshotDisabled test has failed. Please fix the failing test before I can review this PR.

View failed check


Review by Claude | Run

@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 3, 2026

🔧 CI Auto-Fix

Created fix PR: #216

Problem: The test_port_forward_rootless test was failing because slirp4netns rejected port forwarding requests to 10.0.2.100 (invalid guest address).

Solution: Changed to use 10.0.2.15, the standard guest IP in slirp4netns's internal network.

View Claude Run

@ejc3
Copy link
Copy Markdown
Owner Author

ejc3 commented Feb 3, 2026

Superseded by PR #217 (http-proxy) which includes all IPv6 changes plus proxy support

@ejc3 ejc3 closed this Feb 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant