Repository navigation
Conversation
sferrogoo
force-pushed
the
cuttlefish-ipv6-enablement
branch
from
August 28, 2026 15:43
eee6c24 to
c758369
Compare
Contributor
Author
|
@google/android-cuttlefish @adelva1984 @jemoreira PTAL |
sferrogoo
force-pushed
the
cuttlefish-ipv6-enablement
branch
from
September 1, 2026 00:06
cd09095 to
4f5ccc3
Compare
3405691582
requested changes
Sep 3, 2026
dxapd
reviewed
Sep 3, 2026
dxapd
requested changes
Sep 4, 2026
sferrogoo
added a commit
to sferrogoo/android-cuttlefish
that referenced
this pull request
Sep 10, 2026
- Remove duplicate nftables dependency from debian/control. - Roll IPv6 integration tests into existing networking_tests suite. - Factorize IPv6 address polling and connectivity assertions with timeouts. - Separate dual-stack connectivity from IPv6-only flush tests. - Add test host IPv6 bridge check to skip gracefully on IPv4-only hosts.
Contributor
Author
|
Pushed commit 457a75c addressing all review comments:
|
Contributor
Author
|
@dxapd @3405691582 PTAL, addressed all feedback in commit 457a75c. |
sferrogoo
force-pushed
the
cuttlefish-ipv6-enablement
branch
from
September 22, 2026 16:16
1416eae to
8005a2d
Compare
sferrogoo
force-pushed
the
cuttlefish-ipv6-enablement
branch
from
October 6, 2026 16:37
8005a2d to
bd4af35
Compare
sferrogoo
force-pushed
the
cuttlefish-ipv6-enablement
branch
from
October 6, 2026 16:59
bd4af35 to
dca0e84
Compare
…and NAT66 Replace opt-in bridge IPv6 provisioning in cuttlefish-host-resources with default-on Unique Local Address (ULA, RFC 4193) static-mode provisioning: - Configure default ULA prefixes under fd00:cf:20::/44: - cvd-mtap-XX: fd00:cf:21:<i in hex>::1/64 (routed; mobile guest IPv6 via RIL, no RA dnsmasq) - cvd-wbr: fd00:cf:22::1/64 (bridged; RA-only dnsmasq) - cvd-wifiap-XX: fd00:cf:23:<i in hex>::1/64 (routed OpenWrt WAN; RA-only dnsmasq) - cvd-ebr: fd00:cf:24::1/64 (bridged; RA-only dnsmasq) - Keep IPv4 setup and start_dnsmasq/stop_dnsmasq untouched; run start_ipv6 after all IPv4 setup when net.ipv6.conf.all.disable_ipv6=0 and track state via /run/cuttlefish/ipv6-enabled for symmetric teardown. - Run separate RA-only dnsmasq instances (cuttlefish-dnsmasq-ra-<iface>.pid) so IPv6/ICMPv6 issues cannot affect DHCPv4. - Set accept_ra=0 and autoconf=0 on all host cvd-* bridges and tap devices, guarding /proc/sys writes with [ -w ... ] and passing --sysctl net.ipv6.conf.all.forwarding=1 in podcvd for read-only /proc/sys rootless containers. - Add separate IPv6 nftables tables: - ip6 cuttlefish_nat6 postrouting masquerade for fd00:cf:20::/44 leaving non-cvd-* interfaces - bridge cuttlefish_ra_guard prerouting (priority -300) matching meta protocol ip6 meta l4proto ipv6-icmp (including 802.1Q VLAN-0 tagged frames) and dropping nd-router-advert and nd-redirect on cvd-etap-* and cvd-wtap-* - inet cuttlefish_ra_guard input (priority -300) dropping nd-router-advert and nd-redirect on cvd-mtap-* and cvd-wifiap-* Bug: b/549899406 Test: shellcheck -s sh base/debian/cuttlefish-base.cuttlefish-host-resources.init Test: bazel test //host_resources/static_resources_init_test:static_resources_init_test
Derive static-mode cellular IPv6 parameters (ril_ipv6_ipaddr, ril_ipv6_gateway, ril_ipv6_prefixlen) from the host mobile interface (cvd-mbr or cvd-mtap-XX) global/ULA IPv6 address in assemble_cvd via MobileIpv6ConfigFromHostAddress(), set ril_ipv6_dns to 2001:4860:4860::8888, and advertise dual-stack IPv4 + IPv6 PDP context parameters in modem_simulator DataService (AT+CGDCONT and AT+CGCONTRDP) when ril_ipv6_ipaddr is configured while falling back to IPv4-only when no host IPv6 address is present. Bug: b/549899406 Test: bazel test //cuttlefish/host/commands/assemble_cvd/... //cuttlefish/host/commands/modem_simulator/... //cuttlefish/host/libs/config/...
Add docs/networking/openwrt_ipv6_static.md describing the declarative
OpenWrt UCI configuration in AOSP platform/external/openwrt-prebuilts
(shared/config/{network,dhcp,firewall}) for static networking mode:
- wan6 obtains a SLAAC address and default route (sourcefilter 0) from
the host RA on cvd-wifiap-XX (fd00:cf:23:<hex-instance>::/64) or
cvd-wbr (fd00:cf:22::/64).
- globals.ula_prefix is set to fd00:cf:25::/48 with /64 assignments and
odhcpd RA (ra_slaac 1, ra_default 1, dhcpv6 disabled) on wifi0/wifi1.
- br-wifi0 and br-wifi1 use bridge_empty=1 with fixed MAC addresses instead
of enslaving eth0.0/eth0.1 VLAN sub-interfaces.
- firewall wan zone enables masq6=1 for NAT66 alongside IPv4 masq=1.
Bug: b/549899406
Test: none (documentation only)
…ests - Add e2etests/cvd/networking_tests/ipv6_test.go and wire it into //cvd/networking_tests:networking_tests to validate the static-mode ULA prefix plan (fd00:cf:21:<i>::/64, fd00:cf:22::/64, fd00:cf:23:<i>::/64, fd00:cf:24::/64, fd00:cf:25::/48), absence of 2001:db8::/32 addresses, buried_eth0 IPv4 preservation, and optional RIL/OpenWrt/NAT66 egress checks behind --image_ril_ipv6, --image_openwrt_ipv6, and --image_manages_eth1 flags. - Update e2etests/host_resources/static_resources_init_test/main_test.go expectations for cuttlefish_nat6, bridge/inet cuttlefish_ra_guard, /run/cuttlefish/ipv6-enabled, and RA dnsmasq pidfiles. - Use json.RawMessage for nftMatch.Right in e2etests/host_resources/common/nft.go so rules with string right-hand sides (iifname/oifname) unmarshal cleanly. Bug: b/549899406 Test: bazel test //host_resources/static_resources_init_test:static_resources_init_test Test: bazel build //cvd/networking_tests:networking_tests && staticcheck ./...
Private mode (ULA fd00:cf:20::/44 + NAT66) stays the default so guests get
IPv6 on any host. This adds an opt-in routed mode for hosts that own a
routed /48, so that each guest network gets its own global /64 with no
NAT66. That is what CTS ConnectivityManagerTest#testOpenConnection checks:
the address an external server sees must be on the network's link and
differ between Wi-Fi and cellular.
Host init script and defaults:
- New ipv6_routed_prefix=P::/48. Layout: cvd-mtap-NN P:21NN::/64,
cvd-wbr P:22::/64, cvd-wifiap-NN P:23NN::/64, cvd-ebr P:24::/64, OpenWrt
Wi-Fi LAN P:25NN::/64 routed via P:23NN::2. Anything that is not a /48 is
rejected with a message and private mode is used.
- New ipv6_nat=0|1 (default 0 in routed mode, 1 in private mode). Routes
added in routed mode are recorded in /run/cuttlefish/ipv6-routes so stop
removes them.
- start_ipv6 now runs stop_ipv6 first, so a reinstall over a version that
did not stop IPv6 no longer leaves duplicate RA dnsmasq processes.
- Prefix settings are validated; the reason for the fixed fd00:cf prefix
is documented in the defaults file.
openwrt_args.cpp: when cvd-wifiap-NN carries P:23NN::1/64 (routed mode),
pass wan_ip6addr, wan_ip6gw and lan_ip6prefix on the OpenWrt kernel command
line. OpenWrt reads them in external/openwrt-prebuilts 0_default_config.
No new launcher flag is needed.
Tests and docs:
- openwrt_args_test (new), routed-mode cases in network_flags_test and
modem_simulator service_ipv6_test.
- static_resources_init_test: routed-mode addressing, no NAT66, LAN routes,
invalid prefix fallback, ipv6_nat override, start-twice, mode switch.
- networking_tests: TestIPv6RoutedEcho (runs with --routed_echo_url),
helper unit tests, bridged Wi-Fi prefix expectation fixed.
- e2etests/ipv6_upstream_sim: Docker image that plays the upstream router,
echo server and DNS for a routed /48, with a self-test, so routed mode
can be exercised on a machine without a routed prefix.
- docs/networking/ipv6_routed_mode.md; internal references removed from
network_flags.cpp and the docs.
Bug: 549899406
Test: bazel test //cuttlefish/host/libs/config/... //cuttlefish/host/commands/assemble_cvd/... //cuttlefish/host/commands/modem_simulator/...
Test: e2etests: bazel test //host_resources/... ; bazel build //cvd/networking_tests/...
Test: live: private mode, official CtsNetTestCases 1764 pass / 0 fail;
routed mode with the simulator, TestIPv6RoutedEcho pass
…, and harden IPv6 lifecycle
- Replace early-boot net.ipv6.conf.all.forwarding=1 in
90-cuttlefish-ip-forward.conf with net.ipv6.conf.default.accept_ra=2.
In cuttlefish-host-resources.init enable_ipv6_forwarding(), promote
accept_ra from 1 to 2 on default, non-cvd-* interfaces, and any
interface with an RTF_ADDRCONF (0x40000) default route in
/proc/net/ipv6_route before setting net.ipv6.conf.all.forwarding=1, so
addrconf_fixup_forwarding() does not purge the host's SLAAC default
route.
- Add ip6fwd support to manage_nft_rule and insert handle-tracked
iifname/oifname "cvd-*" counter accept rules into table ip6 filter
chain FORWARD so nf_hook_slow accepts Cuttlefish IPv6 forwarding even
when Docker sets ip6tables -P FORWARD DROP.
- Remove '|| true' error suppression across the init script and
ipv6_upstream_sim scripts. Check whether ip_forward / all.forwarding is
already '1' before writing (preserving read-only /proc/sys in podcvd),
gate forwarding sysctl setup on allocate_static_resources=1 after
/.dockerenv device setup, log an explicit error to stderr on write
failure, and abort start_ipv6 when IPv6 forwarding cannot be enabled.
- Harden idempotency, IPv4-only hosts, multi-instance RA cleanup, and
Debian packaging:
* Delete existing handle before re-adding in manage_nft_rule.
* Flush scope global IPv6 addresses on cvd-* bridges and taps and stop
all /var/run/cuttlefish-dnsmasq-ra-*.pid daemons in stop_ipv6().
* Explicitly set disable_ipv6=0 on cvd-mtap-* and cvd-wifiap-* taps in
start_ipv6() for hosts with net.ipv6.conf.default.disable_ipv6=1.
* Clean up cuttlefish-dnsmasq*, routed IPv6 prefixes, nftables
tables/handles, and /run/cuttlefish on purge in
cuttlefish-base.postrm without TOCTOU signal races or unguarded jq.
* Scope second dh_installsystemd call in base/debian/rules with
--remaining-packages to prevent duplicate postinst/prerm snippets.
Bug: 549899406
sferrogoo
force-pushed
the
cuttlefish-ipv6-enablement
branch
from
October 9, 2026 20:35
73268a3 to
b700835
Compare
…ources - Add ParseDns6ServersFromDefaults() and ObtainMobileIpv6Dns() to network_flags.cpp so cellular RIL IPv6 DNS reads dns6_servers from /etc/default/cuttlefish-host-resources when --ril_dns does not already supply an IPv6 server, logging a warning for invalid tokens and falling back to 2001:4860:4860::8888,2001:4860:4860::8844 when unset or unparseable. - Add unit tests in network_flags_test.cc covering custom dns6_servers, commented/unset defaults, whitespace/quotes, mixed IPv4/IPv6 lists, and empty values. Bug: 549899406
…cker FORWARD, and purge - Add TestStaticIPv6PreservesUpstreamRA verifying that starting cuttlefish-host-resources with an active RTF_ADDRCONF default route promotes accept_ra to 2 and preserves the host's IPv6 default route. - Add TestStaticIPv6ForwardAcceptWithDockerDrop verifying that cuttlefish-host-resources adds iifname/oifname "cvd-*" counter accept rules in table ip6 filter chain FORWARD (both before and after Docker sets ip6tables -P FORWARD DROP), forwards IPv6 packets in both directions for cvd-* interfaces while dropping non-cvd-* traffic, and cleanly removes the rules on stop. - Add TestStaticIPv6ForwardingReadOnly verifying read-only IPv6 and IPv4 forwarding sysctl handling (including allocate_static_resources=0) and 90-cuttlefish-ip-forward.conf behavior. - Add TestStaticIPv6DefaultDisableIPv6 verifying tap/bridge IPv6 address and route assignment when net.ipv6.conf.default.disable_ipv6=1. - Add TestStaticIPv6ShrinkAccountsStopsOrphanRaDnsmasq verifying stop_ipv6 terminates all RA dnsmasq instances when num_cvd_accounts is reduced across start/stop. - Add TestStaticIPv6PostrmPurgeCleanup verifying cuttlefish-base.postrm purge removes routed IPv6 prefixes, kills cuttlefish-dnsmasq*, removes nftables rules/tables, and removes /run/cuttlefish. Bug: 549899406
Wire //cvd/networking_tests:networking_tests (hermetic IPv6 and routed echo helper suites) into the e2e-tests-orchestration-runner-special job in .github/workflows/presubmit.yaml. Note that static_resources_init_test is already executed by run-cvd-unit-tests under //host_tests/static_resources_init_test. Bug: 549899406
sferrogoo
force-pushed
the
cuttlefish-ipv6-enablement
branch
from
October 9, 2026 22:04
b700835 to
47ff17d
Compare
…s IPv6 egress On a host with kernel IPv6 enabled (disable_ipv6=0) but no IPv6 default route (typical IPv4-only corporate or home network), advertising default external IPv6 DNS servers (2001:4860:4860::8888/8844) in dnsmasq RAs on cvd-wifiap-XX/cvd-ebr/cvd-wbr and in RIL +CGCONTRDP causes OpenWrt dnsmasq and guest resolvers to send queries that blackhole at the host (failing CTS MultinetworkApiTest#testResNApi with -ETIMEDOUT). Detect host IPv6 egress at start_ipv6 time (ip -6 route show default non-empty, routed mode, or an explicit dns6_servers / ipv6_egress=1 override in /etc/default/cuttlefish-host-resources): - When the host has no IPv6 egress, log a message, omit option6:dns-server from start_ra_dnsmasq while keeping ULA addressing and RA prefix/route advertisements (so DnsTest#testDnsWorks continues to pass), and leave /run/cuttlefish/ipv6-egress absent. - When the host has IPv6 egress, write /run/cuttlefish/ipv6-egress and remove it in stop_ipv6. - In assemble_cvd (ResolveMobileIpv6Dns), omit ril_ipv6_dns when /run/cuttlefish/ipv6-egress is absent and dns6_servers is not explicitly configured in /etc/default/cuttlefish-host-resources. - Add hermetic coverage in static_resources_init_test (TestStaticIPv6EgressDetectionControlsDnsServerAndMarker) and network_flags_test (ResolveMobileIpv6Dns). Bug: 549899406
sferrogoo
force-pushed
the
cuttlefish-ipv6-enablement
branch
from
October 9, 2026 23:38
47ff17d to
3744201
Compare
This branch has not been deployed
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
Gives Cuttlefish guests IPv6 on Ethernet (
eth1), Wi-Fi (wlan0, through OpenWrt) and mobile data (buried_eth0, throughmodem_simulator), set up by the host at boot like the existing IPv4 configuration. IPv4 behavior is unchanged.Two modes, chosen in
/etc/default/cuttlefish-host-resources:fd00:cf:20::/44(fd00:cf:24::/64Ethernet bridge,fd00:cf:22::/64Wi-Fi bridge,fd00:cf:21:<i>::/64mobile,fd00:cf:23:<i>::/64OpenWrt WAN,fd00:cf:25::/64OpenWrt LAN)ipv6_routed_prefix=P::/48)P::/48(P:21NN,P:22,P:23NN,P:24,P:25NN)Routed mode exists because CTS
ConnectivityManagerTest#testOpenConnectionrequires the address an external server sees to be on the network's link and to differ between Wi-Fi and cellular, which NAT cannot satisfy.Commits
cuttlefish-host-resources: ULA prefixes, router advertisements (dnsmasq, separate from the IPv4 DHCP instances), RA guard on the bridges (including 802.1Q VID-0 frames), NAT66, cleanstop,podcvd --sysctlfor forwarding. Honors the newallocate_static_resourcesswitch.assemble_cvd,modem_simulator: the mobile IPv6 address is derived from the hostcvd-mtap-NNaddress;+CGCONTRDPreturns one line per address family (3GPP TS 27.007 §10.1.23).static_resources_init_test(rootless sandbox, no KVM) andnetworking_tests(TestIPv6Provisioning,TestIPv6Nat66Egress).openwrt_args.cppkernel command line keys (wan_ip6addr,wan_ip6gw,lan_ip6prefix),TestIPv6RoutedEcho, a Docker upstream simulator (e2etests/ipv6_upstream_sim/) to exercise routed mode without a routed prefix, and fixes from review and testing.Companion AOSP changes (same bug)
external/openwrt-prebuilts: Wi-Fi LAN ULA +masq6by default; static WAN IPv6 and no NAT66 whenlan_ip6prefixis on the kernel command line.device/generic/goldfishradio HAL: read all+CGCONTRDPlines (dual-stack data calls).packages/modules/ConnectivityCTS: replace theBuild.MODEL.contains("Cuttlefish")skips inDnsTestandtestOpenConnectionwith capability checks.Without the companion changes, this PR alone gives IPv6 on
eth1and keeps IPv4 everywhere;wlan0andburied_eth0IPv6 need the OpenWrt and radio HAL changes in the guest image.Testing
bazel testinbase/cvdforhost/libs/config,assemble_cvd,modem_simulator(with format and tidy): 341/341 pass. Full//...: 1718/1720, the 2 failures are pre-existing environment issues (missinglibclangfor an unrelated camera test).e2etests://host_resources/...pass (15 top-level tests, including routed mode, invalid prefix fallback, start-twice, mode switch);//cvd/networking_tests/...builds; gofmt/vet/staticcheck clean; shellcheck findings on the init script 53 → 44.aosp_cf_x86_64_only_phoneimage with the companion changes:ping6to2001:4860:4860::8888on each, NAT66 counters increase;TestIPv6Provisioning,TestIPv6Nat66Egress,TestDeviceNetworkingpass; bridged Wi-Fi mode pass.CtsNetTestCases,[instant],CtsTetheringTest,CtsNetSecConfig*,CtsVcnTestCases), unmodified APKs: 1,764 pass / 0 fail, per-module counts identical to the no-IPv6 baseline. Note: official CTS skips its IPv6 tests on Cuttlefish by model name; the Connectivity companion change removes those skips.DnsTestpasses with Wi-Fi as default network and with mobile as default network;testOpenConnectionis skipped by the capability check.2001:db8:cf00::/48, isolated network namespace, Docker upstream simulator): no NAT66 rules;buried_eth0gets2001:db8:cf00:2101::2,wlan0gets a2001:db8:cf00:2501::/64SLAAC address;TestIPv6RoutedEchoandTestDeviceNetworkingpass; with the simulator's DNS and lab CA (lab setup, not official CTS)testOpenConnectionandDnsTestpass on both networks.starttwice withoutstop: no duplicate RA daemons or rules;stopleaves no IPv6 state.Bug: b/549899406