Skip to content

support ipv6 localhost relay in Consomme networking mode#40900

Draft
wangxin12 wants to merge 2 commits into
masterfrom
user/wangxin12/virtio-ipv6
Draft

support ipv6 localhost relay in Consomme networking mode#40900
wangxin12 wants to merge 2 commits into
masterfrom
user/wangxin12/virtio-ipv6

Conversation

@wangxin12

Copy link
Copy Markdown
Contributor

Summary of the Pull Request

PR Checklist

  • Closes: Link to issue #xxx
  • Communication: I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected
  • Tests: Added/updated if needed and all pass
  • Localization: All end user facing strings can be localized
  • Dev docs: Added/updated if needed
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

Validation Steps Performed

Copilot AI review requested due to automatic review settings June 25, 2026 07:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends Consomme/mirrored networking to support IPv6 localhost relay end-to-end by provisioning an IPv6 address on the host-created loopback device, adding IPv6 loopback routing/rules in the guest, and introducing a tc/eBPF-based workaround to allow inbound ::1 delivery despite the kernel’s IPv6 “martian” loopback checks on non-loopback devices.

Changes:

  • Provision client_ip_ipv6=::1 for the Consomme loopback device so the host relay can inject ::1 flows onto the GELNIC.
  • Enable the guest IPv6 loopback policy routing + ::1/128 route via the IPv6 loopback gateway, and add an inbound tc/BPF relay path (with a sentinel address + route) to deliver relay-injected ::1 packets.
  • Add an in-tree minimal BPF loader and tooling (BPF program, skeleton generator, and a Makefile to rebuild the embedded header).

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/windows/common/ConsommeNetworking.cpp Adds client_ip_ipv6=::1 to loopback device options when IPv6 + loopback-client mode are enabled.
src/linux/netlinkutil/RoutingTable.cpp Omits RTA_PREFSRC for IPv6 loopback routes to avoid kernel EINVAL with ::1 preferred source.
src/linux/init/NetworkManager.h Extends mirrored loopback rule helper to take address family; adds IPv6 relay configuration helper.
src/linux/init/NetworkManager.cpp Enables IPv6 loopback routing configuration and wires in tc/BPF-based inbound ::1 relay handling.
src/linux/init/Loopback6Bpf.h Declares best-effort loader API returning ingress/egress program fds.
src/linux/init/Loopback6Bpf.cpp Implements minimal loader for embedded tc/BPF bytecode without libbpf.
src/linux/init/GnsEngine.cpp Updates call sites for the updated loopback-rule helper signature.
src/linux/init/CMakeLists.txt Adds new init sources/headers and include path for embedded BPF skeleton header.
src/linux/bpf/Makefile Adds a developer build path to compile the BPF object and regenerate the embedded skeleton header.
src/linux/bpf/loopback6_relay.skel.h Adds generated embedded BPF bytecode + relocation metadata consumed by the in-tree loader.
src/linux/bpf/loopback6_relay.bpf.c Adds tc ingress/egress BPF program implementing the IPv6 localhost relay rewrite/redirect logic.
src/linux/bpf/gen_bpf_skel.py Adds generator producing the embedded skeleton header from a compiled BPF object.

Comment on lines +476 to +495
// Attach the programs to a clsact qdisc on loopback0. Ingress rewrites a relay-injected ::1 source to
// the sentinel, restores ::1 as the destination, and redirects onto lo (whose IFF_LOOPBACK bypasses
// the martian check) so the packet is delivered. Egress restores the relay's addresses on the reply.
gelnic.ModifyTcClassifier(true);
gelnic.BpfAttachTcClassifier(programs->ingressFd, true);
gelnic.BpfAttachTcClassifier(programs->egressFd, false);
close(programs->ingressFd);
close(programs->egressFd);

// The ingress hook redirects packets onto lo, so add the priority-0 "iif lo ... lookup local" rule;
// otherwise the redirected packets would match the priority-1 "lookup 127" rule and be forwarded
// back out instead of delivered locally.
UpdateMirroredLoopbackRulesForInterface("lo", AF_INET6, Operation::Create);

// The egress hook leaves the reply destined to the sentinel; route the sentinel back out loopback0
// (table 127) so it egresses where the hook can rewrite it back to ::1 for the relay.
Route sentinelRoute = Route(AF_INET6, c_ipv6LoopbackGateway, gelnic.Index(), false, c_sentinelV6AddressRange, 0);
sentinelRoute.isLoopbackRoute = true;
loopbackRoutingTable.ModifyRoute(sentinelRoute, Operation::Create);

Comment on lines +191 to +194
if constexpr (std::is_same_v<TAddr, in6_addr>)
{
// The IPv6 loopback destination (::1) cannot be used as a route preferred source on the GELNIC: unlike IPv4
// (where EnableLoopbackRouting turns on route_localnet/accept_local so 127.0.0.1 is a valid source), IPv6 has
Comment on lines +39 to +53
int LoadProgram(const unsigned char* insnBytes, unsigned int insnByteLen, const unsigned int* relocs, unsigned int relocCount, int mapFd)
{
std::vector<uint8_t> insns(insnBytes, insnBytes + insnByteLen);

// Patch the map fd into each ld_imm64 instruction that references the map.
for (unsigned int i = 0; i < relocCount; i++)
{
if (relocs[i] + sizeof(struct bpf_insn) > insns.size())
{
continue;
}
auto* insn = reinterpret_cast<struct bpf_insn*>(insns.data() + relocs[i]);
insn->src_reg = BPF_PSEUDO_MAP_FD;
insn->imm = mapFd;
}
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.

2 participants