From ab2aba2a1dadf32df82566329e8e9624f2cffcc6 Mon Sep 17 00:00:00 2001 From: Nell Jerram Date: Wed, 28 Jan 2026 18:05:06 +0000 Subject: [PATCH 1/3] Fix rendering of NatPortRange in nftables mode --- felix/iptables/actions_test.go | 1 + felix/nftables/actions.go | 2 +- felix/nftables/actions_test.go | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/felix/iptables/actions_test.go b/felix/iptables/actions_test.go index 28c2e8b2fda..6b3732423f6 100644 --- a/felix/iptables/actions_test.go +++ b/felix/iptables/actions_test.go @@ -37,6 +37,7 @@ var _ = DescribeTable("Actions", Entry("SNATAction", environment.Features{}, SNATAction{ToAddr: "10.0.0.1"}, "--jump SNAT --to-source 10.0.0.1"), Entry("SNATAction fully random", environment.Features{SNATFullyRandom: true}, SNATAction{ToAddr: "10.0.0.1"}, "--jump SNAT --to-source 10.0.0.1 --random-fully"), Entry("MasqAction", environment.Features{}, MasqAction{}, "--jump MASQUERADE"), + Entry("MasqAction", environment.Features{}, MasqAction{ToPorts: "32768-65535"}, "--jump MASQUERADE --to-ports 32768-65535"), Entry("MasqAction", environment.Features{MASQFullyRandom: true}, MasqAction{}, "--jump MASQUERADE --random-fully"), Entry("ClearMarkAction", environment.Features{}, ClearMarkAction{Mark: 0x1000}, "--jump MARK --set-mark 0/0x1000"), Entry("SetMarkAction", environment.Features{}, SetMarkAction{Mark: 0x1000}, "--jump MARK --set-mark 0x1000/0x1000"), diff --git a/felix/nftables/actions.go b/felix/nftables/actions.go index 80941fa04bd..7cf81a16413 100644 --- a/felix/nftables/actions.go +++ b/felix/nftables/actions.go @@ -329,7 +329,7 @@ func (g MasqAction) ToFragment(features *environment.Features) string { } if g.ToPorts != "" { // e.g., masquerade to :1024-65535 - return fmt.Sprintf("masquerade to %s"+fullyRand, g.ToPorts) + return fmt.Sprintf("masquerade to :%s"+fullyRand, g.ToPorts) } return "masquerade" + fullyRand } diff --git a/felix/nftables/actions_test.go b/felix/nftables/actions_test.go index e6e0df2f864..bca346b6cce 100644 --- a/felix/nftables/actions_test.go +++ b/felix/nftables/actions_test.go @@ -37,6 +37,7 @@ var _ = DescribeTable("Actions", Entry("SNATAction", environment.Features{}, SNATAction{ToAddr: "10.0.0.1"}, "snat to 10.0.0.1"), Entry("SNATAction fully random", environment.Features{SNATFullyRandom: true}, SNATAction{ToAddr: "10.0.0.1"}, "snat to 10.0.0.1 fully-random"), Entry("MasqAction", environment.Features{}, MasqAction{}, "masquerade"), + Entry("MasqAction", environment.Features{}, MasqAction{ToPorts: "32768-65535"}, "masquerade to :32768-65535"), Entry("MasqAction", environment.Features{MASQFullyRandom: true}, MasqAction{}, "masquerade fully-random"), Entry("ClearMarkAction", environment.Features{}, ClearMarkAction{Mark: 0x1000}, "meta mark set mark & 0xffffefff"), Entry("SetMarkAction", environment.Features{}, SetMarkAction{Mark: 0x1000}, "meta mark set mark or 0x1000"), From c8f4650ba3aae0311437d026a52ff9a2560544e0 Mon Sep 17 00:00:00 2001 From: Nell Jerram Date: Thu, 29 Jan 2026 09:08:05 +0000 Subject: [PATCH 2/3] Add UTs with fully random --- felix/iptables/actions_test.go | 1 + felix/nftables/actions_test.go | 1 + 2 files changed, 2 insertions(+) diff --git a/felix/iptables/actions_test.go b/felix/iptables/actions_test.go index 6b3732423f6..a905fca128e 100644 --- a/felix/iptables/actions_test.go +++ b/felix/iptables/actions_test.go @@ -39,6 +39,7 @@ var _ = DescribeTable("Actions", Entry("MasqAction", environment.Features{}, MasqAction{}, "--jump MASQUERADE"), Entry("MasqAction", environment.Features{}, MasqAction{ToPorts: "32768-65535"}, "--jump MASQUERADE --to-ports 32768-65535"), Entry("MasqAction", environment.Features{MASQFullyRandom: true}, MasqAction{}, "--jump MASQUERADE --random-fully"), + Entry("MasqAction", environment.Features{MASQFullyRandom: true}, MasqAction{ToPorts: "32768-65535"}, "--jump MASQUERADE --to-ports 32768-65535 --random-fully"), Entry("ClearMarkAction", environment.Features{}, ClearMarkAction{Mark: 0x1000}, "--jump MARK --set-mark 0/0x1000"), Entry("SetMarkAction", environment.Features{}, SetMarkAction{Mark: 0x1000}, "--jump MARK --set-mark 0x1000/0x1000"), Entry("SetMaskedMarkAction", environment.Features{}, SetMaskedMarkAction{ diff --git a/felix/nftables/actions_test.go b/felix/nftables/actions_test.go index bca346b6cce..5d27d60f2cd 100644 --- a/felix/nftables/actions_test.go +++ b/felix/nftables/actions_test.go @@ -39,6 +39,7 @@ var _ = DescribeTable("Actions", Entry("MasqAction", environment.Features{}, MasqAction{}, "masquerade"), Entry("MasqAction", environment.Features{}, MasqAction{ToPorts: "32768-65535"}, "masquerade to :32768-65535"), Entry("MasqAction", environment.Features{MASQFullyRandom: true}, MasqAction{}, "masquerade fully-random"), + Entry("MasqAction", environment.Features{MASQFullyRandom: true}, MasqAction{ToPorts: "32768-65535"}, "masquerade to :32768-65535 fully-random"), Entry("ClearMarkAction", environment.Features{}, ClearMarkAction{Mark: 0x1000}, "meta mark set mark & 0xffffefff"), Entry("SetMarkAction", environment.Features{}, SetMarkAction{Mark: 0x1000}, "meta mark set mark or 0x1000"), Entry("SetMaskedMarkAction", environment.Features{}, SetMaskedMarkAction{Mark: 0x1000, Mask: 0xf000}, "meta mark set mark & 0xffff0fff ^ 0x1000"), From 344b8b1eab47b8106c96b40f78b342c7ed060ad5 Mon Sep 17 00:00:00 2001 From: Nell Jerram Date: Thu, 29 Jan 2026 10:05:58 +0000 Subject: [PATCH 3/3] Add FV --- felix/fv/nat_outgoing_test.go | 44 +++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/felix/fv/nat_outgoing_test.go b/felix/fv/nat_outgoing_test.go index 37f8cbfb166..d932b4edd27 100644 --- a/felix/fv/nat_outgoing_test.go +++ b/felix/fv/nat_outgoing_test.go @@ -76,3 +76,47 @@ var _ = infrastructure.DatastoreDescribe("NATOutgoing rule rendering test", []ap } }) }) + +var _ = infrastructure.DatastoreDescribe("NATPortRange rendering test", []apiconfig.DatastoreType{apiconfig.EtcdV3, apiconfig.Kubernetes}, func(getInfra infrastructure.InfraFactory) { + var ( + infra infrastructure.DatastoreInfra + tc infrastructure.TopologyContainers + client client.Interface + ) + + BeforeEach(func() { + var err error + infra = getInfra() + + opts := infrastructure.DefaultTopologyOptions() + opts.IPIPMode = api.IPIPModeNever + opts.EnableIPv6 = true + + opts.ExtraEnvVars = map[string]string{ + "FELIX_NATPortRange": "32768:65535", + } + tc, client = infrastructure.StartSingleNodeTopology(opts, infra) + + ctx := context.Background() + ippool := api.NewIPPool() + ippool.Name = "nat-pool" + ippool.Spec.CIDR = "10.244.255.0/24" + ippool.Spec.NATOutgoing = true + ippool, err = client.IPPools().Create(ctx, ippool, options.SetOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + + It("should have expected rendering", func() { + if NFTMode() { + Eventually(func() string { + output, _ := tc.Felixes[0].ExecOutput("nft", "list", "chain", "ip", "calico", "nat-cali-nat-outgoing") + return output + }, 5*time.Second, 100*time.Millisecond).Should(ContainSubstring("32768-65535")) + } else { + Eventually(func() string { + output, _ := tc.Felixes[0].ExecOutput("iptables-save", "-t", "nat") + return output + }, 5*time.Second, 100*time.Millisecond).Should(ContainSubstring("32768-65535")) + } + }) +})