incremental checksums: NAT - #1809
daniel-noland merged 9 commits into
Conversation
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Essentials Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Essentials Run ID: 📒 Files selected for processing (12)
Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 4 reviews per hour. 📝 WalkthroughWalkthroughNAT translation paths now update transport checksums incrementally where possible and request full refreshes when needed. ICMP error handlers request refresh for outer checksums. VXLAN encapsulation handles IPv6 packets when checksum refresh is not requested. ChangesNAT checksum handling
IPv6 VXLAN encapsulation
Suggested reviewers: Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to NAT now adjusts checksums incrementally instead of forcing a full recomputation for every translated packet. ICMP errors and cases that cannot be updated incrementally still request a full refresh. IPv4 header checksums are still recomputed when packets are sent, and IPv6 VXLAN encapsulation no longer hits an IPv4-only failure path. No outstanding correctness or availability risk was found, and the change looks ready to merge. 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
Comment |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
fb4d35b to
f1b0b79
Compare
f1b0b79 to
4d48896
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Critical checksum correctness issues remain for ICMP-error packets and IPv6 UDP packets with zero checksums.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 4
Open (4)
What changed in this PR
Adds RFC 1624 incremental checksum updates for masquerade, port forwarding, and static NAT to avoid unnecessary full payload recomputation.
Changes:
- Updates NAT checksum handling and preserves recomputation for selected ICMP-error paths.
- Adds checksum correctness, unit, and property-test coverage.
- Removes redundant checksum refresh requests.
| File | Summary |
|---|---|
nat/src/static_nat/test.rs |
Adds end-to-end checksum validation. |
nat/src/static_nat/nf.rs |
Applies incremental static NAT checksum updates. |
nat/src/static_nat/fuzz.rs |
Validates checksum correctness in fuzz properties. |
nat/src/portfw/packet.rs |
Adds incremental port-forwarding checksum updates. |
nat/src/masquerade/test.rs |
Adds NF-level checksum assertions. |
nat/src/masquerade/packet.rs |
Adds incremental masquerade checksum updates. |
nat/src/masquerade/nf.rs |
Removes unconditional checksum refresh. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if modified { | ||
| packet.meta_mut().src_natted(true); | ||
| packet.meta_mut().set_checksum_refresh(true); | ||
| packet.meta_mut().set_checksum_refresh(needs_full_recompute); |
There was a problem hiding this comment.
Agreed, fixed. Headers::has_zero_ipv6_udp_checksum (in #1849, 227566f) flags the case, and masquerade seeds its recompute flag from it in 5e3843c; port forwarding does the same in a770b8a. IPv4 keeps "zero means disabled", as a_disabled_ipv4_udp_quote_checksum_stays_disabled already requires. Each NAT has a test that an IPv6 UDP datagram with a zero checksum comes out requesting a recompute.
4d48896 to
356a841
Compare
The masquerade and port-forwarding ICMP error handlers rewrite the quoted packet, then translate the outer header through the ordinary NAT path. That path used to request a full recompute for every translation, which also covered the quote. With incremental updates it no longer does, so nothing accounted for the quote in the outer ICMP checksum, which covers it. The quote's own checksums are updated alongside it, and a field changed together with the checksum covering it leaves the one's-complement sum unchanged, so often the outer checksum stays right by accident. It does not when the covering checksum is missing: a TCP quote is usually cut off before its checksum (an ICMPv4 error need only quote 8 bytes), and a UDP one may have none. ICMP errors are rare, so both handlers now request a full recompute, as static NAT already did. `assert_checksum_current_or_refresh_requested` is the oracle: either a recompute was requested, or recomputing leaves the transport checksum unchanged. The masquerade ICMP error tests and the two end-to-end ones in `nat/src/test.rs` now apply it. Only the masquerade TCP case exercises the fix; the port-forwarding end-to-end test also runs static NAT, which requests the recompute on its own. Reported in review of #1809. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
356a841 to
c7da5a5
Compare
15ec010 to
3afbdc4
Compare
Add RFC 1624 helpers for port, address, and ICMP identifier changes. Preserve disabled UDP checksums and store computed zeros as 0xFFFF. Request full recomputation for IP version changes and ambiguous ICMPv4 zero results. Compare updates with full recomputation in Bolero properties and test zero-checksum and IP version boundaries. NAT integration follows in #1809. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
3afbdc4 to
36fabb5
Compare
The masquerade and port-forwarding ICMP error handlers rewrite the quoted packet, then translate the outer header through the ordinary NAT path. That path used to request a full recompute for every translation, which also covered the quote. With incremental updates it no longer does, so nothing accounted for the quote in the outer ICMP checksum, which covers it. The quote's own checksums are updated alongside it, and a field changed together with the checksum covering it leaves the one's-complement sum unchanged, so often the outer checksum stays right by accident. It does not when the covering checksum is missing: a TCP quote is usually cut off before its checksum (an ICMPv4 error need only quote 8 bytes), and a UDP one may have none. ICMP errors are rare, so both handlers now request a full recompute, as static NAT already did. `assert_checksum_current_or_refresh_requested` is the oracle: either a recompute was requested, or recomputing leaves the transport checksum unchanged. The masquerade ICMP error tests and the two end-to-end ones in `nat/src/test.rs` now apply it. Only the masquerade TCP case exercises the fix; the port-forwarding end-to-end test also runs static NAT, which requests the recompute on its own. Reported in review of #1809. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ea7a148 to
96535d9
Compare
Add RFC 1624 helpers for port, address, and ICMP identifier changes. Preserve disabled UDP checksums and store computed zeros as 0xFFFF. Request full recomputation for ambiguous ICMPv4 zero results. The address helper is generic over `IpAddress`, so an IP version change cannot be expressed and the update cannot fail. It folds the whole address in one step. `Net::try_set_source_updating_checksum` and `try_set_destination_updating_checksum` set an address and fold it into the transport checksum under the version match `Net` already does. `Headers::net_and_transport_mut` borrows both headers for callers that do not match the header stack. Compare updates with full recomputation in Bolero properties and test the zero-checksum and version-mismatch boundaries. NAT integration follows in #1809. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
36fabb5 to
aecbd87
Compare
96535d9 to
5e9d719
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Critical IPv6 UDP checksum handling gaps and supporting test issues remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 7
Open (8)
Recompute IPv6 UDP zero checksums during NAT · New Handle IPv6 UDP zero checksum in port updates · New Preserve recomputation for IPv6 UDP zero checksums · New IPv6 UDP zero checksum leaves incremental update falsely successful ICMP error checksum refresh skipped after quoted header mutation ICMP error checksum refresh skipped after quoted header mutation IPv6 UDP zero checksum incorrectly skips checksum recomputation Exclude valid IPv4 UDP zero checksums from comparison · New
| ) -> Result<(), NatPacketError> { | ||
| let mut modified = false; | ||
| // Request a full recomputation when a checksum delta cannot be applied. | ||
| let mut needs_full_recompute = false; |
| if !tp.increment_checksum_for_u16(p.get(), new_src_port.get()) { | ||
| needs_full_recompute = true; | ||
| } |
| let nfi = self.name(); | ||
| debug!("{nfi}: Changing IP src: {} -> {target_src}", net.src_addr()); | ||
| net.try_set_source(target_src) | ||
| net.try_set_source_updating_checksum(target_src, transport) |
| if packet.meta().checksum_refresh() { | ||
| return; | ||
| } |
Add RFC 1624 helpers for port, address, and ICMP identifier changes. Preserve disabled IPv4 UDP checksums and store computed zeros as 0xFFFF. `Headers::has_zero_ipv6_udp_checksum` flags the IPv6 zero, which only a full recompute can repair. Request full recomputation for ambiguous ICMPv4 zero results. The address helper is generic over `IpAddress`, so an IP version change cannot be expressed and the update cannot fail. It folds the whole address in one step. `Net::try_set_source_updating_checksum` and `try_set_destination_updating_checksum` set an address and fold it into the transport checksum under the version match `Net` already does. `Headers::net_and_transport_mut` borrows both headers for callers that do not match the header stack. Compare updates with full recomputation in Bolero properties and test the zero-checksum and version-mismatch boundaries. NAT integration follows in #1809. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
aecbd87 to
227566f
Compare
5e9d719 to
25889f1
Compare
Add RFC 1624 helpers for port, address, and ICMP identifier changes. Preserve disabled IPv4 UDP checksums and store computed zeros as 0xFFFF. `Headers::has_zero_ipv6_udp_checksum` flags the IPv6 zero, which only a full recompute can repair. Request full recomputation for ambiguous ICMPv4 zero results. The address helper is generic over `IpAddress`, so an IP version change cannot be expressed and the update cannot fail. It folds the whole address in one step. `Net::try_set_source_updating_checksum` and `try_set_destination_updating_checksum` set an address and fold it into the transport checksum under the version match `Net` already does. Compare updates with full recomputation in Bolero properties. A further property covers what a checksum-correct packet never reaches: unchanged values, a missing transport, and disabled UDP checksums. Test the zero-checksum and version-mismatch boundaries. NAT integration follows in #1809. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
227566f to
7d57087
Compare
25889f1 to
75ba0b2
Compare
Build ICMPv4 and ICMPv6 echo requests so NAT tests can exercise identifier and checksum updates. Each builder rejects the other family's ICMP. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Skip header checksum updates for IPv6, which has no header checksum. Add a regression test for VXLAN encapsulation without a refresh request. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Use `Transport` for ICMPv4 and ICMPv6 identifier updates so checksum helpers can dispatch by version. Identifier errors now use `TransportError::UnsupportedIdentifier`. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Apply address, port, and ICMP identifier deltas with the new `Transport` helpers, requesting full recomputation when needed, including for an IPv6 UDP checksum of zero, which cannot take a delta. Compare SNAT and DNAT results with full recomputation for TCP and ICMP. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Let `snat` and `dnat` decide when a refresh is needed. Check through the network function that translations produce correct checksums without requesting full recomputation. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Apply address and port checksum deltas in both translation directions. Keep ICMPv4 checksums unchanged for address-only updates and adjust ICMPv6 pseudo-header checksums. Request full recomputation for an IPv6 UDP checksum of zero, which cannot take a delta. Compare translated checksums with full recomputation in tests. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Fold address changes as they are set, borrowing the network and transport headers together through `Headers::net_and_transport_mut`. Capture port deltas before translation and apply them after the `TcpUdpMut` borrow ends. Keep full recomputation for ICMP errors, whose checksums cover the quote, and for an IPv6 UDP checksum of zero, which cannot take a delta. Check checksum validity in the marking properties and add a test through `StaticNat::process`. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Only set `checksum_refresh` when recomputation is needed; leave existing requests intact when an update succeeds incrementally. `Packet::update_checksums` clears the flag after recomputation. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Request full recomputation in masquerade and port-forwarding ICMP error handlers because the outer checksum covers the modified quote. A truncated TCP checksum or disabled UDP checksum can prevent inner checksum updates from preserving the outer sum. Add a shared assertion for current checksums or pending refresh requests and apply it to ICMP error tests, including a port-forwarding test through the ICMP error handler. Signed-off-by: Daniel Noland <daniel@githedgehog.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
75ba0b2 to
a879a71
Compare
43db9d6
into
pr/daniel-noland/incremental-checksum-net


No description provided.