Skip to content

Automated backport of #3979: Fix IPv6 protocol conflict in nftables rules#3987

Merged
tpantelis merged 2 commits intosubmariner-io:release-0.23from
tpantelis:automated-backport-of-#3979-upstream-release-0.23
Apr 20, 2026
Merged

Automated backport of #3979: Fix IPv6 protocol conflict in nftables rules#3987
tpantelis merged 2 commits intosubmariner-io:release-0.23from
tpantelis:automated-backport-of-#3979-upstream-release-0.23

Conversation

@tpantelis
Copy link
Copy Markdown
Contributor

@tpantelis tpantelis commented Apr 16, 2026

Backport of #3979 on release-0.23.

#3979: Fix IPv6 protocol conflict in nftables rules

For details on the backport process, see the backport requests page.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced IPv6 support for packet filtering with improved dual-stack network handling
  • Tests

    • Added IPv6-specific test validation for protocol processing
    • Expanded end-to-end test coverage with additional dual-stack configuration variants

Remove RuleActionSelfSNAT from the generic rule action map.
IPv6 rules were failing because the generic "snat to ip saddr"
was being applied to all IP families. This needs per-family
handling.

Add tests to verify IPv6 protocol headers work correctly.

Signed-off-by: Tom Pantelis <tompantelis@gmail.com>
@submariner-bot
Copy link
Copy Markdown
Contributor

🤖 Created branch: z_pr3987/tpantelis/automated-backport-of-#3979-upstream-release-0.23
🚀 Full E2E won't run until the "ready-to-test" label is applied. I will add it automatically once the PR has 2 approvals, or you can add it manually.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

Walkthrough

This pull request introduces IPv6 support to nftables packet filtering. Changes include removing RuleActionSelfSNAT from the mapping, adding IPv6-aware rule-spec generation that threads an isIPv6 flag through protocol and address family handling, introducing IPv6-specific test assertions, and extending the E2E test matrix with a nftables, dual-stack combination.

Changes

Cohort / File(s) Summary
GitHub Actions E2E Workflow
.github/workflows/e2e.yml
Added nftables, dual-stack combination to the E2E test matrix for extended IPv6 coverage.
Packet Filter Mapping
pkg/packetfilter/nftables/nftables.go
Removed packetfilter.RuleActionSelfSNAT entry from ruleActionToStr mapping; formatting adjustments to remaining entries.
IPv6 Test Suite
pkg/packetfilter/nftables/nftables_test.go
Added new Describe("IPv6 rules") test suite with three assertions: UDP rules use ip6 nexthdr udp, ICMP rules use ip6 nexthdr icmpv6, and SelfSNAT actions serialize to snat to ip6 saddr.
IPv6 Rule Conversion Logic
pkg/packetfilter/nftables/rule_conversion.go
Introduced isIPv6 parameter threading through protoToRuleSpec and setToRuleSpec; updated protocol clause generation to emit ip protocol for IPv4 and ip6 nexthdr for IPv6 with ICMP-to-icmpv6 mapping; modified RuleActionSelfSNAT handling to emit family-aware snat to clauses.

Sequence Diagram

sequenceDiagram
    participant Client
    participant RuleConverter as Rule Converter
    participant ProtoHandler as Protocol Handler
    participant FamilyHandler as Address Family Handler
    participant ActionHandler as Action Handler
    participant Renderer as NFTables Renderer

    Client->>RuleConverter: toNftRuleSpec(rule, isIPv6=true)
    
    RuleConverter->>ProtoHandler: protoToRuleSpec(protocol, isIPv6=true)
    
    alt IPv6 Protocol Branch
        ProtoHandler->>FamilyHandler: Check if UDP/TCP/ICMP
        alt ICMP Protocol
            FamilyHandler->>FamilyHandler: Map ICMP → icmpv6
            FamilyHandler->>Renderer: Emit "ip6 nexthdr icmpv6"
        else Other Protocols
            FamilyHandler->>Renderer: Emit "ip6 nexthdr <proto>"
        end
    else IPv4 Protocol Branch
        ProtoHandler->>Renderer: Emit "ip protocol <proto>"
    end
    
    RuleConverter->>ActionHandler: Handle RuleActionSelfSNAT
    
    alt SelfSNAT Action
        ActionHandler->>Renderer: Emit "snat to ip6 saddr" (if IPv6) or "snat to ip saddr" (if IPv4)
    else Other Actions
        ActionHandler->>Renderer: Emit ruleActionToStr[action]
    end
    
    Renderer->>Client: Return serialized rule spec
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Fix IPv6 protocol conflict in nftables rules #3979: Implements identical IPv6 nftables packet filter changes including removal of RuleActionSelfSNAT from the mapping, IPv6-aware rule generation with per-family SelfSNAT handling, and corresponding test additions and E2E matrix updates.

Suggested labels

ready-to-test, release-note-needed

Suggested reviewers

  • mkolesnik
  • Oats87
  • skitt
  • yboaron
  • vthapar
  • sridhargaddam
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: fixing an IPv6 protocol conflict in nftables rules through an automated backport, which directly relates to the core modifications across the nftables package.
Actionable Comments Resolved ✅ Passed The IPv6 rules test now correctly uses Not(ContainSubstring("ip protocol icmp")) instead of the tautological assertion, properly validating IPv6 ICMP rules use ip6 nexthdr icmpv6 format.

✏️ 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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
pkg/packetfilter/nftables/rule_conversion.go (1)

98-140: Core fix looks correct.

The explicit snat to <prefix> saddr emission for RuleActionSelfSNAT (lines 136–140) using the computed setPrefix correctly produces snat to ip saddr for IPv4 and snat to ip6 saddr for IPv6, resolving the protocol conflict that stemmed from a single hard-coded mapping in ruleActionToStr.

Optional nit: setPrefix is computed identically here (lines 101–105) and inside setToRuleSpec (lines 81–85). Passing setPrefix into setToRuleSpec (or computing it once at the top and reusing) would eliminate the small duplication — but this is purely cosmetic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/packetfilter/nftables/rule_conversion.go` around lines 98 - 140, The code
computes setPrefix twice (once in toNftRuleSpec and again inside setToRuleSpec)
which is duplicate; modify to compute setPrefix once in toNftRuleSpec and pass
that variable into setToRuleSpec (add a parameter to setToRuleSpec and update
its callers) so setPrefix is reused, keeping the existing behavior for IPv4/IPv6
and leaving the explicit RuleActionSelfSNAT handling unchanged.
pkg/packetfilter/nftables/nftables_test.go (1)

403-452: Nice, targeted IPv6 coverage.

The new suite precisely targets the three IPv6-specific rendering rules changed in rule_conversion.go (UDP nexthdr, ICMPv6, and per-family SelfSNAT), and correctly uses fakeNft6.Fake.ListRules to bypass the wrapper that clears the Rule field.

One optional thought: consider also adding a symmetric IPv4 assertion for RuleActionSelfSNAT (expecting snat to ip saddr) so both family branches in toNftRuleSpec are covered, since this is the regression at the heart of the PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/packetfilter/nftables/nftables_test.go` around lines 403 - 452, Add a
symmetric IPv4 assertion for the SelfSNAT rendering: in the IPv4 test suite
(where the IPv4 driver/pf is created, analogous to fakeNft6/pf6 and
getRuleSpec6), append a test that calls pf.Append with
packetfilter.RuleActionSelfSNAT and then asserts the rendered rule (via the fake
nft ListRules helper used for IPv4) contains "snat to ip saddr"; reference the
same symbols used in the IPv6 tests (RuleActionSelfSNAT, Append, and the fake
nft ListRules wrapper) so both branches exercised by toNftRuleSpec are covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/packetfilter/nftables/nftables_test.go`:
- Around line 440-443: The negative assertion in the IPv6 ICMP test is checking
the wrong IPv4 substring; update the assertion that references getRuleSpec6() to
assert Not(ContainSubstring("ip protocol icmp")) instead of
Not(ContainSubstring("ip nexthdr icmp")) so it mirrors the IPv4 UDP/ICMP check
(see the UDP assertion near lines 431–432) and actually prevents accidental
IPv4-style formatting being emitted.

---

Nitpick comments:
In `@pkg/packetfilter/nftables/nftables_test.go`:
- Around line 403-452: Add a symmetric IPv4 assertion for the SelfSNAT
rendering: in the IPv4 test suite (where the IPv4 driver/pf is created,
analogous to fakeNft6/pf6 and getRuleSpec6), append a test that calls pf.Append
with packetfilter.RuleActionSelfSNAT and then asserts the rendered rule (via the
fake nft ListRules helper used for IPv4) contains "snat to ip saddr"; reference
the same symbols used in the IPv6 tests (RuleActionSelfSNAT, Append, and the
fake nft ListRules wrapper) so both branches exercised by toNftRuleSpec are
covered.

In `@pkg/packetfilter/nftables/rule_conversion.go`:
- Around line 98-140: The code computes setPrefix twice (once in toNftRuleSpec
and again inside setToRuleSpec) which is duplicate; modify to compute setPrefix
once in toNftRuleSpec and pass that variable into setToRuleSpec (add a parameter
to setToRuleSpec and update its callers) so setPrefix is reused, keeping the
existing behavior for IPv4/IPv6 and leaving the explicit RuleActionSelfSNAT
handling unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9bedb5d9-07d3-4e40-846a-a057ee354bd9

📥 Commits

Reviewing files that changed from the base of the PR and between c11e58d and eedbdb9.

📒 Files selected for processing (4)
  • .github/workflows/e2e.yml
  • pkg/packetfilter/nftables/nftables.go
  • pkg/packetfilter/nftables/nftables_test.go
  • pkg/packetfilter/nftables/rule_conversion.go

Comment thread pkg/packetfilter/nftables/nftables_test.go
@tpantelis
Copy link
Copy Markdown
Contributor Author

@coderabbitai approve

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

✅ Actions performed

Comments resolved and changes approved.

@tpantelis tpantelis added the ready-to-test When a PR is ready for full E2E testing label Apr 20, 2026
@tpantelis tpantelis merged commit 24672d5 into submariner-io:release-0.23 Apr 20, 2026
75 of 79 checks passed
@submariner-bot
Copy link
Copy Markdown
Contributor

🤖 Closed branches: [z_pr3987/tpantelis/automated-backport-of-#3979-upstream-release-0.23]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automated-backport ready-to-test When a PR is ready for full E2E testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants