feat: Generalize NAT66Shard into EgressShard for both address families - #22
Merged
Merged
Conversation
NAT64 (RFC 6146) and NAT66 are the same function -- stateful egress PAT with a VRF-scoped session table, port allocation, and decap/re-encap on the return path -- over different address families. Rather than add a second, near-duplicate kind alongside NAT66Shard, this renames it to EgressShard and widens its status to describe whichever families a given shard actually serves. Status gains ShardAddressIPv4 and NAT64Prefix, and ShardAddress becomes ShardAddressIPv6. A shard serving only NAT66 leaves both new fields empty and is byte-for-byte the shape NAT66Shard had, so the generalization is additive for the IPv6 half rather than a behavior change to it. ShardAddressIPv4 is deliberately documented as not BGP-advertised into the EVPN fabric the way ShardAddressIPv6 is: an IPv4 reply arrives from the internet, so that address has to be attracted to the node by the underlay or an upstream announcement. Publishing it in status is what makes that operator prerequisite checkable instead of implicit. NAT64Prefix is echoed in status because it is the one fact DNS64 synthesis must agree with -- a shard translating for a different prefix than the resolver synthesizes into is otherwise a silent blackhole with no observable symptom on either side. The CEL validations now pin address family explicitly (ip(self).family()), which the previous isIP()-only rules did not, so an IPv4 literal in an IPv6 field is rejected at admission rather than at datapath load. No conversion path or dual-shape reconciliation window is provided: no NAT66Shard object exists in any cluster, so this is a rename rather than a migration. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
scotwells
approved these changes
Sep 11, 2026
This was referenced Sep 11, 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
Prerequisite API change for NAT64 egress (enhancements#879).
NAT64 and NAT66 are the same function over different address families. This renames
NAT66ShardtoEgressShardand widens its status to describe whichever families a shard serves, instead of adding a near-duplicate kind.ShardAddress→ShardAddressIPv6ShardAddressIPv4— empty means no NAT64NAT64Prefix— the value DNS64 synthesis must agree withip(self).family(), so an IPv4 literal in an IPv6 field fails admission rather than datapath loadA shard serving only NAT66 leaves both new fields empty and keeps
NAT66Shard's exact shape.ShardAddressIPv4is documented as not advertised into the EVPN fabric. A NAT64 reply arrives from the IPv4 internet, so the underlay or an upstream announcement must attract that address to the node. Status publishes it so the prerequisite is checkable.No conversion path: no
NAT66Shardexists in any cluster, so this is a rename, not a migration.docs/api/bgp.md's diff size is the alphabetical re-sort from the type name change.Test plan
task generate; generated output committedgo build ./...,go test ./api/...task lint— 0 issues🤖 Generated with Claude Code