Skip to content

Commit d12d99b

Browse files
authored
feat: remove jump to swift-postrouting in iptables legacy as rules already exist in iptables nftables (#3958)
* add logic to delete jump to swift postrouting in legacy and fix uts * revert ut edits * address linter * align getting iptables legacy with iptables * update log * fail silently should iptables legacy interface fail to create
1 parent 11ac589 commit d12d99b

File tree

5 files changed

+64
-3
lines changed

5 files changed

+64
-3
lines changed

cns/fakes/iptablesfake.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@ var (
1616
errIndexBounds = errors.New("index out of bounds")
1717
)
1818

19+
type IPTablesLegacyMock struct {
20+
deleteCallCount int
21+
}
22+
23+
func (c *IPTablesLegacyMock) Delete(_, _ string, _ ...string) error {
24+
c.deleteCallCount++
25+
return nil
26+
}
27+
28+
func (c *IPTablesLegacyMock) DeleteCallCount() int {
29+
return c.deleteCallCount
30+
}
31+
1932
type IPTablesMock struct {
2033
state map[string]map[string][]string
2134
clearChainCallCount int

cns/restserver/internalapi_linux.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package restserver
33
import (
44
"fmt"
55
"net"
6+
"os/exec"
67
"strconv"
78

89
"github.com/Azure/azure-container-networking/cns"
@@ -22,6 +23,16 @@ func (c *IPtablesProvider) GetIPTables() (iptablesClient, error) {
2223
client, err := goiptables.New()
2324
return client, errors.Wrap(err, "failed to get iptables client")
2425
}
26+
func (c *IPtablesProvider) GetIPTablesLegacy() (iptablesLegacyClient, error) {
27+
return &iptablesLegacy{}, nil
28+
}
29+
30+
type iptablesLegacy struct{}
31+
32+
func (c *iptablesLegacy) Delete(table, chain string, rulespec ...string) error {
33+
cmd := append([]string{"-t", table, "-D", chain}, rulespec...)
34+
return errors.Wrap(exec.Command("iptables-legacy", cmd...).Run(), "iptables legacy failed delete")
35+
}
2536

2637
// nolint
2738
func (service *HTTPRestService) programSNATRules(req *cns.CreateNetworkContainerRequest) (types.ResponseCode, string) {
@@ -32,6 +43,18 @@ func (service *HTTPRestService) programSNATRules(req *cns.CreateNetworkContainer
3243
// in podsubnet case, ncPrimaryIP is the pod subnet's primary ip
3344
// in vnet scale case, ncPrimaryIP is the node's ip
3445
ncPrimaryIP, _, _ := net.ParseCIDR(req.IPConfiguration.IPSubnet.IPAddress + "/" + fmt.Sprintf("%d", req.IPConfiguration.IPSubnet.PrefixLength))
46+
47+
iptl, err := service.iptables.GetIPTablesLegacy()
48+
if err == nil {
49+
err = iptl.Delete(iptables.Nat, iptables.Postrouting, "-j", SWIFTPOSTROUTING)
50+
// ignore if command fails
51+
if err == nil {
52+
logger.Printf("[Azure CNS] Deleted legacy jump to SWIFT-POSTROUTING Chain")
53+
}
54+
} else {
55+
logger.Printf("[Azure CNS] Could not create iptables legacy interface, continuing : %v", err)
56+
}
57+
3558
ipt, err := service.iptables.GetIPTables()
3659
if err != nil {
3760
return types.UnexpectedError, fmt.Sprintf("[Azure CNS] Error. Failed to create iptables interface : %v", err)
@@ -130,7 +153,7 @@ func (service *HTTPRestService) programSNATRules(req *cns.CreateNetworkContainer
130153
// if rule count doesn't match or not all rules exist, reconcile
131154
// add one because there is always a singular starting rule in the chain, in addition to the ones we add
132155
if len(currentRules) != len(rules)+1 || !allRulesExist {
133-
logger.Printf("[Azure CNS] Reconciling SWIFT-POSTROUTING chain rules")
156+
logger.Printf("[Azure CNS] Reconciling SWIFT-POSTROUTING chain rules to SNAT Azure DNS and IMDS to Host IP")
134157

135158
err = ipt.ClearChain(iptables.Nat, SWIFTPOSTROUTING)
136159
if err != nil {
@@ -143,6 +166,7 @@ func (service *HTTPRestService) programSNATRules(req *cns.CreateNetworkContainer
143166
return types.FailedToRunIPTableCmd, "[Azure CNS] failed to append rule to SWIFT-POSTROUTING chain : " + err.Error()
144167
}
145168
}
169+
logger.Printf("[Azure CNS] Finished reconciling SWIFT-POSTROUTING chain")
146170
}
147171

148172
// we only need to run this code once as the iptable rule applies to all secondary ip configs in the same subnet

cns/restserver/internalapi_linux_test.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import (
1515
)
1616

1717
type FakeIPTablesProvider struct {
18-
iptables *fakes.IPTablesMock
18+
iptables *fakes.IPTablesMock
19+
iptablesLegacy *fakes.IPTablesLegacyMock
1920
}
2021

2122
func (c *FakeIPTablesProvider) GetIPTables() (iptablesClient, error) {
@@ -26,6 +27,13 @@ func (c *FakeIPTablesProvider) GetIPTables() (iptablesClient, error) {
2627
return c.iptables, nil
2728
}
2829

30+
func (c *FakeIPTablesProvider) GetIPTablesLegacy() (iptablesLegacyClient, error) {
31+
if c.iptablesLegacy == nil {
32+
c.iptablesLegacy = &fakes.IPTablesLegacyMock{}
33+
}
34+
return c.iptablesLegacy, nil
35+
}
36+
2937
func TestAddSNATRules(t *testing.T) {
3038
type chainExpectation struct {
3139
table string
@@ -307,8 +315,10 @@ func TestAddSNATRules(t *testing.T) {
307315
t.Run(tt.name, func(t *testing.T) {
308316
service := getTestService(cns.KubernetesCRD)
309317
ipt := fakes.NewIPTablesMock()
318+
iptl := &fakes.IPTablesLegacyMock{}
310319
service.iptables = &FakeIPTablesProvider{
311-
iptables: ipt,
320+
iptables: ipt,
321+
iptablesLegacy: iptl,
312322
}
313323

314324
// setup pre-existing rules
@@ -360,6 +370,12 @@ func TestAddSNATRules(t *testing.T) {
360370
if actualClearChainCalls != tt.expectedClearChainCalls {
361371
t.Fatalf("ClearChain call count mismatch: got %d, expected %d", actualClearChainCalls, tt.expectedClearChainCalls)
362372
}
373+
374+
// verify we delete legacy swift postrouting jump
375+
actualLegacyDeleteCalls := iptl.DeleteCallCount()
376+
if actualLegacyDeleteCalls != 1 {
377+
t.Fatalf("Delete call count mismatch: got %d, expected 1", actualLegacyDeleteCalls)
378+
}
363379
})
364380
}
365381
}

cns/restserver/internalapi_windows.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ func (*IPtablesProvider) GetIPTables() (iptablesClient, error) {
2424
return nil, errUnsupportedAPI
2525
}
2626

27+
func (*IPtablesProvider) GetIPTablesLegacy() (iptablesLegacyClient, error) {
28+
return nil, errUnsupportedAPI
29+
}
30+
2731
// nolint
2832
func (service *HTTPRestService) programSNATRules(req *cns.CreateNetworkContainerRequest) (types.ResponseCode, string) {
2933
return types.Success, ""

cns/restserver/restserver.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,13 @@ type iptablesClient interface {
6464
ClearChain(table string, chain string) error
6565
Delete(table, chain string, rulespec ...string) error
6666
}
67+
type iptablesLegacyClient interface {
68+
Delete(table, chain string, rulespec ...string) error
69+
}
6770

6871
type iptablesGetter interface {
6972
GetIPTables() (iptablesClient, error)
73+
GetIPTablesLegacy() (iptablesLegacyClient, error)
7074
}
7175

7276
// HTTPRestService represents http listener for CNS - Container Networking Service.

0 commit comments

Comments
 (0)