Skip to content

Commit 00b385d

Browse files
committed
fix: improve iptables version detection
Signed-off-by: Hunter Gregory <[email protected]>
1 parent 571afbc commit 00b385d

File tree

4 files changed

+98
-77
lines changed

4 files changed

+98
-77
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ require (
130130
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0
131131
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0
132132
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0
133+
github.com/zcalusic/sysinfo v1.1.2
133134
golang.org/x/sync v0.8.0
134135
gotest.tools/v3 v3.5.1
135136
k8s.io/kubectl v0.28.5

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZla
294294
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
295295
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
296296
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
297+
github.com/zcalusic/sysinfo v1.1.2 h1:38KUgZQmCxlN9vUTt4miis4rU5ISJXGXOJ2rY7bMC8g=
298+
github.com/zcalusic/sysinfo v1.1.2/go.mod h1:NX+qYnWGtJVPV0yWldff9uppNKU4h40hJIRPf/pGLv4=
297299
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
298300
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
299301
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=

npm/pkg/dataplane/dataplane_linux.go

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
11
package dataplane
22

33
import (
4+
"errors"
5+
"fmt"
6+
"strconv"
7+
"strings"
8+
9+
"github.com/Azure/azure-container-networking/common"
10+
"github.com/Azure/azure-container-networking/npm/metrics"
411
"github.com/Azure/azure-container-networking/npm/pkg/dataplane/policies"
512
"github.com/Azure/azure-container-networking/npm/util"
613
npmerrors "github.com/Azure/azure-container-networking/npm/util/errors"
14+
15+
"github.com/zcalusic/sysinfo"
16+
"k8s.io/klog"
717
)
818

19+
const detectingErrMsg = "failed to detect iptables version. failed to find KUBE chains in iptables-legacy-save and iptables-nft-save and failed to get kernel version. NPM will crash to retry"
20+
21+
var errDetectingIptablesVersion = errors.New(detectingErrMsg)
22+
923
func (dp *DataPlane) getEndpointsToApplyPolicies(_ []*policies.NPMNetworkPolicy) (map[string]string, error) {
1024
// NOOP in Linux
1125
return nil, nil
@@ -21,7 +35,9 @@ func (dp *DataPlane) updatePod(pod *updateNPMPod) error {
2135
}
2236

2337
func (dp *DataPlane) bootupDataPlane() error {
24-
util.DetectIptablesVersion(dp.ioShim)
38+
if err := detectIptablesVersion(dp.ioShim); err != nil {
39+
return npmerrors.ErrorWrapper(npmerrors.BootupDataplane, false, "failed to detect iptables version", err)
40+
}
2541

2642
// It is important to keep order to clean-up ACLs before ipsets. Otherwise we won't be able to delete ipsets referenced by ACLs
2743
if err := dp.policyMgr.Bootup(nil); err != nil {
@@ -37,3 +53,81 @@ func (dp *DataPlane) refreshPodEndpoints() error {
3753
// NOOP in Linux
3854
return nil
3955
}
56+
57+
// detectIptablesVersion sets the global iptables variable to nft if detected or legacy if detected.
58+
// NPM will crash if it fails to detect either.
59+
// This global variable is referenced in all iptables related functions.
60+
func detectIptablesVersion(ioShim *common.IOShim) error {
61+
klog.Info("first attempt detecting iptables version. running: iptables-nft-save -t mangle")
62+
cmd := ioShim.Exec.Command(util.IptablesSaveNft, "-t", "mangle")
63+
output, err := cmd.CombinedOutput()
64+
if err == nil && strings.Contains(string(output), "KUBE-IPTABLES-HINT") || strings.Contains(string(output), "KUBE-KUBELET-CANARY") {
65+
msg := "detected iptables version on first attempt. found KUBE chains in nft tables. NPM will use iptables-nft"
66+
klog.Info(msg)
67+
metrics.SendLog(util.DaemonDataplaneID, msg, metrics.DonotPrint)
68+
util.Iptables = util.IptablesNft
69+
util.IptablesSave = util.IptablesSaveNft
70+
util.IptablesRestore = util.IptablesRestoreNft
71+
return nil
72+
}
73+
74+
if err != nil {
75+
msg := fmt.Sprintf("failed to detect iptables version on first attempt. error running iptables-nft-save. will try detecting using iptables-legacy-save. err: %w", err)
76+
klog.Info(msg)
77+
metrics.SendErrorLogAndMetric(util.DaemonDataplaneID, msg)
78+
}
79+
80+
klog.Info("second attempt detecting iptables version. running: iptables-legacy-save -t mangle")
81+
lCmd := ioShim.Exec.Command(util.IptablesSaveLegacy, "-t", "mangle")
82+
loutput, err := lCmd.CombinedOutput()
83+
if err == nil && strings.Contains(string(loutput), "KUBE-IPTABLES-HINT") || strings.Contains(string(loutput), "KUBE-KUBELET-CANARY") {
84+
msg := "detected iptables version on second attempt. found KUBE chains in legacy tables. NPM will use iptables-legacy"
85+
klog.Info(msg)
86+
metrics.SendLog(util.DaemonDataplaneID, msg, metrics.DonotPrint)
87+
util.Iptables = util.IptablesLegacy
88+
util.IptablesSave = util.IptablesSaveLegacy
89+
util.IptablesRestore = util.IptablesRestoreLegacy
90+
return nil
91+
}
92+
93+
if err != nil {
94+
msg := fmt.Sprintf("failed to detect iptables version on second attempt. error running iptables-legacy-save. will try detecting using kernel version. err: %w", err)
95+
klog.Info(msg)
96+
metrics.SendErrorLogAndMetric(util.DaemonDataplaneID, msg)
97+
}
98+
99+
klog.Info("third attempt detecting iptables version. getting kernel version")
100+
var si sysinfo.SysInfo
101+
si.GetSysInfo()
102+
kernelVersion := strings.Split(si.Kernel.Release, ".")
103+
if kernelVersion[0] == "" {
104+
msg := fmt.Sprintf("failed to detect iptables version on third attempt. error getting kernel version. err: %w", err)
105+
klog.Info(msg)
106+
metrics.SendErrorLogAndMetric(util.DaemonDataplaneID, msg)
107+
return errDetectingIptablesVersion
108+
}
109+
110+
majorVersion, err := strconv.Atoi(kernelVersion[0])
111+
if err != nil {
112+
msg := fmt.Sprintf("failed to detect iptables version on third attempt. error converting kernel version to int. err: %w", err)
113+
klog.Info(msg)
114+
metrics.SendErrorLogAndMetric(util.DaemonDataplaneID, msg)
115+
return errDetectingIptablesVersion
116+
}
117+
118+
if majorVersion >= 5 {
119+
msg := "detected iptables version on third attempt. found kernel version >= 5. NPM will use iptables-nft"
120+
klog.Info(msg)
121+
metrics.SendLog(util.DaemonDataplaneID, msg, metrics.DonotPrint)
122+
util.Iptables = util.IptablesNft
123+
util.IptablesSave = util.IptablesSaveNft
124+
util.IptablesRestore = util.IptablesRestoreNft
125+
return nil
126+
}
127+
128+
msg := "detected iptables version on third attempt. found kernel version < 5. NPM will use iptables-legacy"
129+
klog.Info(msg)
130+
metrics.SendLog(util.DaemonDataplaneID, msg, metrics.DonotPrint)
131+
132+
return nil
133+
}

npm/util/const.go

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,6 @@
22
// MIT License
33
package util
44

5-
import (
6-
"bytes"
7-
"fmt"
8-
"strings"
9-
10-
"github.com/Azure/azure-container-networking/common"
11-
)
12-
135
// kubernetes related constants.
146
const (
157
KubeSystemFlag string = "kube-system"
@@ -271,71 +263,3 @@ const (
271263
DaemonDataplaneID // for v2
272264
FanOutServerID // for v2
273265
)
274-
275-
func DetectIptablesVersion(ioShim *common.IOShim) {
276-
cmd := ioShim.Exec.Command(IptablesSaveNft, "-t", "mangle")
277-
278-
output, err := cmd.CombinedOutput()
279-
if err != nil {
280-
fmt.Printf("Error running iptables-nft-save: %s", err)
281-
return
282-
}
283-
284-
if strings.Contains(string(output), "KUBE-IPTABLES-HINT") || strings.Contains(string(output), "KUBE-KUBELET-CANARY") {
285-
Iptables = IptablesNft
286-
IptablesSave = IptablesSaveNft
287-
IptablesRestore = IptablesRestoreNft
288-
} else {
289-
lCmd := ioShim.Exec.Command(IptablesSaveLegacy, "-t", "mangle")
290-
291-
loutput, err := lCmd.CombinedOutput()
292-
if err != nil {
293-
fmt.Printf("Error running iptables-legacy-save: %s", err)
294-
return
295-
}
296-
297-
if strings.Contains(string(loutput), "KUBE-IPTABLES-HINT") || strings.Contains(string(loutput), "KUBE-KUBELET-CANARY") {
298-
Iptables = IptablesLegacy
299-
IptablesSave = IptablesSaveLegacy
300-
IptablesRestore = IptablesRestoreLegacy
301-
} else {
302-
lsavecmd := ioShim.Exec.Command(IptablesSaveNft)
303-
lsaveoutput, err := lsavecmd.CombinedOutput()
304-
if err != nil {
305-
fmt.Printf("Error running iptables-nft-save: %s", err)
306-
return
307-
}
308-
309-
lcount := countLines(lsaveoutput)
310-
311-
savecmd := ioShim.Exec.Command(IptablesSaveLegacy)
312-
saveoutput, err := savecmd.CombinedOutput()
313-
if err != nil {
314-
fmt.Printf("Error running iptables-legacy-save: %s", err)
315-
return
316-
}
317-
318-
count := countLines(saveoutput)
319-
320-
if lcount > count {
321-
Iptables = IptablesLegacy
322-
IptablesSave = IptablesSaveLegacy
323-
IptablesRestore = IptablesRestoreLegacy
324-
} else {
325-
Iptables = IptablesNft
326-
IptablesSave = IptablesSaveNft
327-
IptablesRestore = IptablesRestoreNft
328-
}
329-
}
330-
}
331-
}
332-
333-
func countLines(output []byte) int {
334-
count := 0
335-
for _, x := range bytes.Split(output, []byte("\n")) {
336-
if len(x) >= 1 && x[0] == '-' {
337-
count++
338-
}
339-
}
340-
return count
341-
}

0 commit comments

Comments
 (0)