Skip to content

feat: Generalize NAT66Shard into EgressShard for both address families - #22

Merged
privateip merged 1 commit into
mainfrom
feat/egress-shard-nat64
Sep 11, 2026
Merged

privateip merged 1 commit into
mainfrom
feat/egress-shard-nat64

Conversation

@privateip

@privateip privateip commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Prerequisite API change for NAT64 egress (enhancements#879).

NAT64 and NAT66 are the same function over different address families. This renames NAT66Shard to EgressShard and widens its status to describe whichever families a shard serves, instead of adding a near-duplicate kind.

  • ShardAddressShardAddressIPv6
  • new ShardAddressIPv4 — empty means no NAT64
  • new NAT64Prefix — the value DNS64 synthesis must agree with
  • CEL now pins address family via ip(self).family(), so an IPv4 literal in an IPv6 field fails admission rather than datapath load

A shard serving only NAT66 leaves both new fields empty and keeps NAT66Shard's exact shape.

ShardAddressIPv4 is 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 NAT66Shard exists 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 committed
  • go build ./..., go test ./api/...
  • task lint — 0 issues
  • galactic builds against this

🤖 Generated with Claude Code

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>
@privateip
privateip requested a review from a team as a code owner September 11, 2026 17:24
@privateip
privateip merged commit ec15d7b into main Sep 11, 2026
6 checks passed
@privateip
privateip deleted the feat/egress-shard-nat64 branch September 11, 2026 17:51
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