Skip to content

NAT: ICMP Error checksums validation clean-up#1587

Merged
qmonnet merged 8 commits into
mainfrom
pr/qmonnet/icmp-checksums
Jun 24, 2026
Merged

NAT: ICMP Error checksums validation clean-up#1587
qmonnet merged 8 commits into
mainfrom
pr/qmonnet/icmp-checksums

Conversation

@qmonnet

@qmonnet qmonnet commented Jun 10, 2026

Copy link
Copy Markdown
Member

Some clean-ups for checksum validation for ICMP Error messages.

Please refer to individual commits for details.

Fixes: #1586

@qmonnet qmonnet self-assigned this Jun 10, 2026
@qmonnet qmonnet requested a review from a team as a code owner June 10, 2026 17:06
@qmonnet qmonnet added the area/nat Related to Network Address Translation (NAT) label Jun 10, 2026
@qmonnet qmonnet enabled auto-merge June 10, 2026 17:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 IcmpErrorHandler via the shared validate_checksums_icmp() helper, removing the bespoke validation function.
  • Simplified stateless NAT ICMP-inner-translation gating by computing an icmp_err boolean 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.

Comment thread nat/src/static_nat/nf.rs
Comment thread nat/src/icmp_handler/icmp_error_msg.rs Outdated
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@qmonnet, we couldn't start this review because you've reached your PR review rate limit.

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ac39dcfa-746d-4207-aa08-ca99902dd2cc

📥 Commits

Reviewing files that changed from the base of the PR and between 67f56bd and 02e8ec7.

📒 Files selected for processing (10)
  • nat/src/icmp_handler/icmp_error_msg.rs
  • nat/src/icmp_handler/nf.rs
  • net/src/flows/flow_key.rs
  • net/src/headers/embedded.rs
  • net/src/icmp4/truncated.rs
  • net/src/icmp6/truncated.rs
  • net/src/packet/icmp_err.rs
  • net/src/packet/mod.rs
  • net/src/tcp/truncated.rs
  • net/src/udp/truncated.rs
📝 Walkthrough

Walkthrough

ICMP 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.

Changes

ICMP validation and NAT flow updates

Layer / File(s) Summary
Packet ICMP inspection helpers
net/src/packet/utils.rs
is_icmp_error() is simplified, and is_icmp_error_with_embedded_packet() is added to detect ICMP error packets that include embedded headers.
ICMP error validation and outcomes
nat/src/icmp_handler/icmp_error_msg.rs
IcmpErrorMsgError adds NotIcmp; DoneReason mappings change for non-ICMP and missing embedded headers; validate_checksums_icmp() returns Err(NotIcmp) for non-ICMP packets and Ok(()) for ICMP query messages, and tests cover the new checksum and embedded-header outcomes.
ICMP handler uses shared checksum validation
nat/src/icmp_handler/nf.rs
The ICMP error handler imports validate_checksums_icmp, removes its local checksum helper, calls the shared validator in handle_icmp_error_msg(), and drops the explicit packet.update_checksums() call before static NAT metadata is set.
Static NAT threads embedded-ICMP flag
nat/src/static_nat/nf.rs
Static NAT removes is_icmp_inner_translation_candidate, computes icmp_err once in translate() with is_icmp_error_with_embedded_packet(), passes it into source_nat() and destination_nat(), gates embedded inner translation on that flag, and narrows the reprocessing filter to embedded ICMP error packets.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: ICMP error checksum validation cleanup in NAT.
Description check ✅ Passed The description is related to the checksum-validation cleanup and references the linked fix.
Linked Issues check ✅ Passed The changes align with #1586 by validating ICMP error checksums once in shared handling before inner NAT translation.
Out of Scope Changes check ✅ Passed The changed files stay focused on ICMP checksum handling and supporting NAT logic; no clear unrelated additions stand out.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ 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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
nat/src/stateless/nf.rs (1)

270-283: ICMP checksum validation is enforced before StatelessNat in the dataplane pipeline

dataplane/src/packet_processor/mod.rs adds icmp_error_handler before static_nat (StatelessNat), and IcmpErrorHandler::process drops packets that fail validate_checksums_icmp(...), so the skip of local checksum validation in nat/src/stateless/nf.rs (ICMP error NAT fast path) matches the pipeline contract.

Remaining gap: nat/src/stateless/test.rs calls StatelessNat::process directly for ICMP error cases (no IcmpErrorHandler stage), 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

📥 Commits

Reviewing files that changed from the base of the PR and between 58da74b and 5110c1f.

📒 Files selected for processing (4)
  • nat/src/icmp_handler/icmp_error_msg.rs
  • nat/src/icmp_handler/nf.rs
  • nat/src/stateless/nf.rs
  • net/src/packet/utils.rs

@qmonnet qmonnet force-pushed the pr/qmonnet/icmp-checksums branch from 5110c1f to 5ca15fa Compare June 10, 2026 19:48
@qmonnet qmonnet force-pushed the pr/qmonnet/icmp-checksums branch from 5ca15fa to 054a648 Compare June 17, 2026 10:14
Comment thread nat/src/icmp_handler/icmp_error_msg.rs Outdated
Comment thread nat/src/icmp_handler/icmp_error_msg.rs Outdated

@Fredi-raspall Fredi-raspall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just have two minor comments, which are not blocking.

@qmonnet qmonnet added this pull request to the merge queue Jun 24, 2026
@qmonnet qmonnet removed this pull request from the merge queue due to a manual request Jun 24, 2026
qmonnet added 4 commits June 24, 2026 16:09
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>
@qmonnet qmonnet force-pushed the pr/qmonnet/icmp-checksums branch from 054a648 to 67f56bd Compare June 24, 2026 14:18
qmonnet added 4 commits June 24, 2026 15:25
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>
@qmonnet qmonnet enabled auto-merge June 24, 2026 14:25
@qmonnet qmonnet added this pull request to the merge queue Jun 24, 2026
Merged via the queue into main with commit 5f19b51 Jun 24, 2026
34 of 35 checks passed
@qmonnet qmonnet deleted the pr/qmonnet/icmp-checksums branch June 24, 2026 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/nat Related to Network Address Translation (NAT)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

stateless NAT: validate ICMP checksums before destination-side inner translation

3 participants