Skip to content

Commit 8ee59c6

Browse files
champtarMarcelo Guerrero Viveros
authored andcommitted
portmap: fix CHECK for nftables backend
Fixes 01a94e1 Signed-off-by: Etienne Champetier <[email protected]>
1 parent 372953d commit 8ee59c6

File tree

2 files changed

+100
-32
lines changed

2 files changed

+100
-32
lines changed

plugins/meta/portmap/portmap_nftables.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,14 +246,24 @@ func (pmNFT *portMapperNFTables) checkPorts(config *PortMapConf, containerNet ne
246246
var hostPorts, hostIPHostPorts, masqueradings int
247247
for _, e := range config.RuntimeConfig.PortMaps {
248248
if e.HostIP != "" {
249-
hostIPHostPorts++
249+
hostIP := net.ParseIP(e.HostIP)
250+
isHostV6 := (hostIP.To4() == nil)
251+
// Ignore wrong-IP-family HostIPs
252+
if isV6 != isHostV6 {
253+
continue
254+
}
255+
if hostIP.IsUnspecified() {
256+
hostPorts++
257+
} else {
258+
hostIPHostPorts++
259+
}
250260
} else {
251261
hostPorts++
252262
}
253263
}
254264
if *config.SNAT {
255-
masqueradings = len(config.RuntimeConfig.PortMaps)
256-
if isV6 {
265+
masqueradings = 1
266+
if !isV6 {
257267
masqueradings *= 2
258268
}
259269
}

plugins/meta/portmap/portmap_nftables_test.go

Lines changed: 87 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,31 @@ import (
2727

2828
var _ = Describe("portmapping configuration (nftables)", func() {
2929
containerID := "icee6giejonei6so"
30+
configTmpl := `{
31+
"name": "test",
32+
"type": "portmap",
33+
"cniVersion": "%s",
34+
"backend": "nftables",
35+
"runtimeConfig": {
36+
"portMappings": [
37+
{ "hostPort": 8080, "containerPort": 80, "protocol": "tcp"},
38+
{ "hostPort": 8081, "containerPort": 80, "protocol": "tcp"},
39+
{ "hostPort": 8080, "containerPort": 81, "protocol": "udp"},
40+
{ "hostPort": 8082, "containerPort": 82, "protocol": "udp"},
41+
{ "hostPort": 8083, "containerPort": 83, "protocol": "tcp", "hostIP": "192.168.0.2"},
42+
{ "hostPort": 8084, "containerPort": 84, "protocol": "tcp", "hostIP": "0.0.0.0"},
43+
{ "hostPort": 8085, "containerPort": 85, "protocol": "tcp", "hostIP": "2001:db8:a::1"},
44+
{ "hostPort": 8086, "containerPort": 86, "protocol": "tcp", "hostIP": "::"}
45+
]
46+
},
47+
"snat": true,
48+
"conditionsV4": ["a", "b"],
49+
"conditionsV6": ["c", "d"]
50+
}`
51+
containerNet4, err := types.ParseCIDR("10.0.0.2/24")
52+
Expect(err).NotTo(HaveOccurred())
53+
containerNet6, err := types.ParseCIDR("2001:db8::2/64")
54+
Expect(err).NotTo(HaveOccurred())
3055

3156
for _, ver := range []string{"0.3.0", "0.3.1", "0.4.0", "1.0.0"} {
3257
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
@@ -45,37 +70,14 @@ var _ = Describe("portmapping configuration (nftables)", func() {
4570
}
4671
})
4772

48-
It(fmt.Sprintf("[%s] generates correct rules on ADD", ver), func() {
49-
configBytes := []byte(fmt.Sprintf(`{
50-
"name": "test",
51-
"type": "portmap",
52-
"cniVersion": "%s",
53-
"backend": "nftables",
54-
"runtimeConfig": {
55-
"portMappings": [
56-
{ "hostPort": 8080, "containerPort": 80, "protocol": "tcp"},
57-
{ "hostPort": 8081, "containerPort": 80, "protocol": "tcp"},
58-
{ "hostPort": 8080, "containerPort": 81, "protocol": "udp"},
59-
{ "hostPort": 8082, "containerPort": 82, "protocol": "udp"},
60-
{ "hostPort": 8083, "containerPort": 83, "protocol": "tcp", "hostIP": "192.168.0.2"},
61-
{ "hostPort": 8084, "containerPort": 84, "protocol": "tcp", "hostIP": "0.0.0.0"},
62-
{ "hostPort": 8085, "containerPort": 85, "protocol": "tcp", "hostIP": "2001:db8:a::1"},
63-
{ "hostPort": 8086, "containerPort": 86, "protocol": "tcp", "hostIP": "::"}
64-
]
65-
},
66-
"snat": true,
67-
"conditionsV4": ["a", "b"],
68-
"conditionsV6": ["c", "d"]
69-
}`, ver))
73+
It(fmt.Sprintf("[%s] generates correct rules", ver), func() {
74+
configBytes := []byte(fmt.Sprintf(configTmpl, ver))
7075

7176
conf, _, err := parseConfig(configBytes, "foo")
7277
Expect(err).NotTo(HaveOccurred())
7378
conf.ContainerID = containerID
7479

75-
containerNet, err := types.ParseCIDR("10.0.0.2/24")
76-
Expect(err).NotTo(HaveOccurred())
77-
78-
err = pmNFT.forwardPorts(conf, *containerNet)
80+
err = pmNFT.forwardPorts(conf, *containerNet4)
7981
Expect(err).NotTo(HaveOccurred())
8082

8183
expectedRules := strings.TrimSpace(`
@@ -103,10 +105,8 @@ add rule ip cni_hostport prerouting a b jump hostports
103105

104106
// Disable snat, generate IPv6 rules
105107
*conf.SNAT = false
106-
containerNet, err = types.ParseCIDR("2001:db8::2/64")
107-
Expect(err).NotTo(HaveOccurred())
108108

109-
err = pmNFT.forwardPorts(conf, *containerNet)
109+
err = pmNFT.forwardPorts(conf, *containerNet6)
110110
Expect(err).NotTo(HaveOccurred())
111111

112112
expectedRules = strings.TrimSpace(`
@@ -129,6 +129,64 @@ add rule ip6 cni_hostport prerouting c d jump hostports
129129
actualRules = strings.TrimSpace(ipv6Fake.Dump())
130130
Expect(actualRules).To(Equal(expectedRules))
131131
})
132+
133+
It(fmt.Sprintf("[%s] has working CHECK", ver), func() {
134+
configBytes := []byte(fmt.Sprintf(configTmpl, ver))
135+
136+
conf, _, err := parseConfig(configBytes, "foo")
137+
Expect(err).NotTo(HaveOccurred())
138+
conf.ContainerID = containerID
139+
140+
// CHECK KO: Missing all rules
141+
err = pmNFT.checkPorts(conf, *containerNet4)
142+
Expect(err).To(HaveOccurred())
143+
err = pmNFT.checkPorts(conf, *containerNet6)
144+
Expect(err).To(HaveOccurred())
145+
146+
*conf.SNAT = false
147+
148+
// ADD with SNAT=false
149+
err = pmNFT.forwardPorts(conf, *containerNet4)
150+
Expect(err).NotTo(HaveOccurred())
151+
err = pmNFT.forwardPorts(conf, *containerNet6)
152+
Expect(err).NotTo(HaveOccurred())
153+
154+
// CHECK OK: no SNAT rules
155+
err = pmNFT.checkPorts(conf, *containerNet4)
156+
Expect(err).NotTo(HaveOccurred())
157+
err = pmNFT.checkPorts(conf, *containerNet6)
158+
Expect(err).NotTo(HaveOccurred())
159+
160+
*conf.SNAT = true
161+
162+
// CHECK KO: missing SNAT rules
163+
err = pmNFT.checkPorts(conf, *containerNet4)
164+
Expect(err).To(HaveOccurred())
165+
err = pmNFT.checkPorts(conf, *containerNet6)
166+
Expect(err).To(HaveOccurred())
167+
168+
// ADD with SNAT=true
169+
err = pmNFT.forwardPorts(conf, *containerNet4)
170+
Expect(err).NotTo(HaveOccurred())
171+
err = pmNFT.forwardPorts(conf, *containerNet6)
172+
Expect(err).NotTo(HaveOccurred())
173+
174+
// CHECK OK: All rules present
175+
err = pmNFT.checkPorts(conf, *containerNet4)
176+
Expect(err).NotTo(HaveOccurred())
177+
err = pmNFT.checkPorts(conf, *containerNet6)
178+
Expect(err).NotTo(HaveOccurred())
179+
180+
// DELETE
181+
err = pmNFT.unforwardPorts(conf)
182+
Expect(err).NotTo(HaveOccurred())
183+
184+
// CHECK KO: Missing all rules
185+
err = pmNFT.checkPorts(conf, *containerNet4)
186+
Expect(err).To(HaveOccurred())
187+
err = pmNFT.checkPorts(conf, *containerNet6)
188+
Expect(err).To(HaveOccurred())
189+
})
132190
})
133191
}
134192
})

0 commit comments

Comments
 (0)