NAT: ICMP Error checksums validation clean-up#1587
Conversation
There was a problem hiding this comment.
Pull request overview
This PR refactors ICMP error handling around checksum validation and inner-packet translation, aiming to centralize validation in the ICMP error handler stage and simplify stateless NAT’s ICMP-specific logic (per issue #1586).
Changes:
- Added a
Packet::is_icmp_error_with_embedded_packet()helper and simplified ICMP error detection. - Moved ICMP checksum validation usage into
IcmpErrorHandlervia the sharedvalidate_checksums_icmp()helper, removing the bespoke validation function. - Simplified stateless NAT ICMP-inner-translation gating by computing an
icmp_errboolean once and reusing it for both NAT directions.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| net/src/packet/utils.rs | Adds a packet helper to detect ICMP errors that include an embedded fragment. |
| nat/src/stateless/nf.rs | Simplifies ICMP inner translation gating and relies on earlier pipeline-stage validation. |
| nat/src/icmp_handler/nf.rs | Switches to shared ICMP checksum validation and removes the local validator. |
| nat/src/icmp_handler/icmp_error_msg.rs | Cleans up checksum-validation errors/mappings and adjusts tests for the new behavior. |
|
Warning Review limit reached
More reviews will be available in 53 minutes and 22 seconds. Learn how PR review limits work. To continue reviewing without waiting, enable usage-based billing in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (10)
📝 WalkthroughWalkthroughICMP checksum validation now separates non-ICMP packets from ICMP error messages, and static NAT uses a precomputed embedded-ICMP flag for inner-packet translation. The ICMP handler now calls the shared validator, and packet utilities expose embedded-header detection. ChangesICMP validation and NAT flow updates
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
nat/src/stateless/nf.rs (1)
270-283: ICMP checksum validation is enforced before StatelessNat in the dataplane pipelinedataplane/src/packet_processor/mod.rs adds
icmp_error_handlerbeforestatic_nat(StatelessNat), andIcmpErrorHandler::processdrops packets that failvalidate_checksums_icmp(...), so the skip of local checksum validation innat/src/stateless/nf.rs(ICMP error NAT fast path) matches the pipeline contract.Remaining gap:
nat/src/stateless/test.rscallsStatelessNat::processdirectly for ICMP error cases (noIcmpErrorHandlerstage), so invalid-checksum behavior depends on caller/test preconditions—document that precondition or add an end-to-end regression that confirms bad ICMP checksums are dropped before NAT.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@nat/src/stateless/nf.rs` around lines 270 - 283, Tests call StatelessNat::process directly for ICMP error packets but the real dataplane guarantees validate_checksums_icmp runs in IcmpErrorHandler::process before StatelessNat; update nat/src/stateless/test.rs to either (preferred) invoke the full pipeline or explicitly run validate_checksums_icmp and drop packets with bad checksums before calling StatelessNat::process so behavior matches production, or at minimum add a regression test that runs IcmpErrorHandler::process followed by StatelessNat::process to assert packets with invalid ICMP checksums are dropped and not NATed; refer to StatelessNat::process, IcmpErrorHandler::process, and validate_checksums_icmp when making the change.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@nat/src/stateless/nf.rs`:
- Around line 270-283: Tests call StatelessNat::process directly for ICMP error
packets but the real dataplane guarantees validate_checksums_icmp runs in
IcmpErrorHandler::process before StatelessNat; update nat/src/stateless/test.rs
to either (preferred) invoke the full pipeline or explicitly run
validate_checksums_icmp and drop packets with bad checksums before calling
StatelessNat::process so behavior matches production, or at minimum add a
regression test that runs IcmpErrorHandler::process followed by
StatelessNat::process to assert packets with invalid ICMP checksums are dropped
and not NATed; refer to StatelessNat::process, IcmpErrorHandler::process, and
validate_checksums_icmp when making the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: bab16958-95ec-4b38-8970-64ce45da5bdb
📒 Files selected for processing (4)
nat/src/icmp_handler/icmp_error_msg.rsnat/src/icmp_handler/nf.rsnat/src/stateless/nf.rsnet/src/packet/utils.rs
5110c1f to
5ca15fa
Compare
5ca15fa to
054a648
Compare
Fredi-raspall
left a comment
There was a problem hiding this comment.
I just have two minor comments, which are not blocking.
Create a new helper for the Packet type to check that a packet is 1) an ICMP Error message, and 2) actually has an embedded IP header. This allows skipping the static NAT stage if there's no embedded headers to process. Signed-off-by: Quentin Monnet <qmo@qmon.net>
In the case of ICMP Error messages requiring static NAT for both source and destination, there is no need to check for the presence of an inner packet twice: we can check once in translate(), using the new Packet helper is_icmp_error_with_embedded_packet(), and pass the result to the methods doing source and destination NAT. Signed-off-by: Quentin Monnet <qmo@qmon.net>
For static NAT, we've got some asymmetry for checksum validation between source and destination NAT. This is because when we need to apply both source and destination NAT for a packet, the source address (and potentially source port) has changed after NAT, making the checksums invalid when we start destination NAT. But this asymmetry is an issue if we only do destination NAT on the packet, because in that case we don't validate the checksums. Instead, we should move checksum validation to the parent translate() method, before doing source NAT. But in fact, there is no need to validate the checksums at all for ICMP Error messages in the static NAT pipeline stage: this is because the stage assumes that packets have been through the ICMP Error handler first, where checksums are already validated. So we can just skip validation entirely (but leave a comment in translate()). Signed-off-by: Quentin Monnet <qmo@qmon.net>
We had two nearly-identical validation functions for the checksums for ICMP packets (in particular, for the inner checksums in ICMP Error messages): validate_checksums_icmp() and icmp_checksums_ok(). After a recent change in the static NAT stage, validate_checksums_icmp() is no longer used outside of tests, so it makes no sense to keep the two different functions. Merge them together. As part of this, we rework the errors generated from the resulting functions, and the way they translate into DoneReason variants, in order to maintain a consistent behaviour for the ICMP Error messages handler. Signed-off-by: Quentin Monnet <qmo@qmon.net>
054a648 to
67f56bd
Compare
Implement trait From for EmbeddedTransport, and for its variants, so that we can turn directly a Tcp object directly into EmbeddedTransport, for example. Some of the implementations are only available (and used) for the test target. More specifically, we implement: - For<Tcp> for TruncatedTcp - For<Tcp> for EmbeddedTransport - For<TruncatedTcpHeader> for TruncatedTcp - For<TruncatedTcpHeader> for EmbeddedTransport - For<Udp> for TruncatedUdp - For<Udp> for EmbeddedTransport - For<TruncatedUdpHeader> for TruncatedUdp - For<TruncatedUdpHeader> for EmbeddedTransport - For<Icmp4> for TruncatedIcmp4 - For<Icmp4> for EmbeddedTransport - For<TruncatedIcmp4Header> for TruncatedIcmp4 - For<TruncatedIcmp4Header> for EmbeddedTransport - For<Icmp6> for TruncatedIcmp6 - For<Icmp6> for EmbeddedTransport - For<TruncatedIcmp6Header> for TruncatedIcmp6 - For<TruncatedIcmp6Header> for EmbeddedTransport Signed-off-by: Quentin Monnet <qmo@qmon.net>
Add an IcmpErrorPacket view of a Packet. This is in fact not a complete view, but a holder for references to its outer IP header, (outer) ICMP header, ICMP payload, inner IP header, and inner transport header. The view is read-only, and is only created if all of these headers (including the inner transport header) are present for the packet. This view will help process ICMP Error messages in a future commit. Signed-off-by: Quentin Monnet <qmo@qmon.net>
Rather than re-validating that the packet has an outer IP, ICMP, inner IP and inner transport layers, use the IcmpErrorPacket view to validate just once at the beginning of the ICMP Error messages handler, and use the view when we need read-only checks or flowkey extraction from the packet. Signed-off-by: Quentin Monnet <qmo@qmon.net>
Now that we've moved to the IcmpErrorPacket view in the ICMP Error handler code, we can remove function validate_checksums_icmp() which is no longer used outside of tests. Tests can be adjusted to use the IcmpErrorPacket view as well, and its method validate_checksums(). Move unit tests related to checksum validation to net/src/packet/icmp_err.rs, where they now belong. Most of these tests now validate whether we manage to form a valid IcmpErrorPacket view from a packet, rather than the result from the checksum validation: they were adjusted and renamed accordingly. Add a test to check that the view fails when we have an ICMP Error message with embedded packet fragment, but without an embedded transport layer. The bolero tests, which check the full translation in addition to the checksum update, remain at the same location. One adjustment is that we now only check the checksums when we are supposed to be able to form a valid IcmpErrorPacket, in other words, when the generated packet contains an inner transport layer. Signed-off-by: Quentin Monnet <qmo@qmon.net>
Some clean-ups for checksum validation for ICMP Error messages.
Please refer to individual commits for details.
Fixes: #1586