feat(gateway): add egress masquerade datapath to edgenat.c - #381
Open
privateip wants to merge 1 commit into
Open
feat(gateway): add egress masquerade datapath to edgenat.c#381privateip wants to merge 1 commit into
privateip wants to merge 1 commit into
Conversation
scotwells
approved these changes
Aug 13, 2026
This was referenced Aug 13, 2026
Contributor
Author
|
The test failures are expected. Need to merge datum-cloud/network#15 first. |
This was referenced Aug 13, 2026
Phase B of #865, per docs/plans/865-edge-gateway-nat66-egress.md §3. Adds egress_config_table, egress_conn_table, handle_egress_forward, handle_egress_return, and the updated 4-way top-level dispatch in edge_nat(). tenant_arg (the egress_sid locator's uFMT Argument bits) keys the forward row so two tenants with colliding ULA backend addresses never collide in egress_conn_table. backend_usid (needed to route replies back to the originating worker node) is captured directly from the egress-forward packet's own outer SRv6 source address, since Phase B proposes no per-tenant policy table to look it up from. This assumes RouteEgressAdd's SEG6 encap route always stamps the originating node's own uSID as that outer source, consistent with every other cross-node SRv6 packet in this codebase, but that has not been independently verified here -- flagged in the code and worth confirming before Phase D's e2e proof relies on it. handle_egress_return drops any non-TCP/UDP protocol addressed to masq_addr (e.g. ICMPv6) rather than passing it to the kernel stack, the same fail-closed convention gw_addr's own return branch already uses for claimed addresses -- a real cost for an internet-facing address that gw_addr's internal-only precedent didn't have to weigh. Tests cover both new branches end-to-end (SNAT/DNAT, checksum, real FIB-resolved L2), non-SYN/no-conn drops, PAT exhaustion, and the tenant-isolation scenario the plan's §6 calls out explicitly: two tenants presenting the same colliding backend_addr:port->dest_addr:port tuple via distinct tenant_arg values resolve to two independent egress_conn_table rows and masq_port allocations.
privateip
force-pushed
the
feat/865-egress-phase-b
branch
from
August 14, 2026 01:15
0886b06 to
9c0a1c6
Compare
This was referenced Aug 14, 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
Phase B of #865, per docs/plans/865-edge-gateway-nat66-egress.md §3.
Stacked on #380 (Phase A).
egress_config_table,egress_conn_table,handle_egress_forward,handle_egress_return, updated 4-way dispatch inedge_nat().tenant_arg(egress_sid's uFMT Argument bits) keys the forward row,so two tenants with colliding ULA backend addresses never collide in
egress_conn_table.dropreason.go.Flagged for review
backend_usid(needed to route replies back to the originatingworker node) has no per-tenant policy table in Phase B. Resolved by
reading it off the wire -- the egress-forward packet's own outer
SRv6 source address, captured before the outer header is stripped.
Assumes
RouteEgressAdd's SEG6 encap route always stamps theoriginating node's own uSID as that outer source, consistent with
every other cross-node SRv6 packet in this codebase -- not
independently verified here. Marked in the code; worth confirming
before Phase D's e2e proof depends on it.
handle_egress_returndrops any non-TCP/UDP protocol addressed tomasq_addr(e.g. ICMPv6) rather than passing it to the kernelstack -- same fail-closed convention
gw_addr's own return branchuses for claimed addresses, but a real cost for an internet-facing
address that
gw_addr's internal-only precedent didn't have toweigh.
Testing
edgenat_egress_test.go: both branchesend-to-end (SNAT/DNAT, checksum, real FIB-resolved L2), non-SYN/no-conn
drops, PAT exhaustion, and the tenant-isolation scenario §6 calls out
explicitly (colliding backend/dest tuple, distinct
tenant_arg->two independent rows and
masq_portallocations).go build ./...,go vet ./...,task lint(0 issues) -- clean.edgenatsuite passes under root +-race.task test:unit: one pre-existing, unrelated failure ininternal/cni/tap(environment-specific -- confirmed on theunmodified branch too).
🤖 Generated with Claude Code