Skip to content

Commit 01a94e1

Browse files
danwinshipsqueed
authored andcommitted
Add nftables backend to portmap
Signed-off-by: Dan Winship <[email protected]>
1 parent 3d1968c commit 01a94e1

File tree

4 files changed

+632
-0
lines changed

4 files changed

+632
-0
lines changed

Diff for: plugins/meta/portmap/main.go

+78
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"github.com/containernetworking/cni/pkg/types"
3838
current "github.com/containernetworking/cni/pkg/types/100"
3939
"github.com/containernetworking/cni/pkg/version"
40+
"github.com/containernetworking/plugins/pkg/utils"
4041
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
4142
)
4243

@@ -46,6 +47,12 @@ type PortMapper interface {
4647
unforwardPorts(config *PortMapConf) error
4748
}
4849

50+
// These are vars rather than consts so we can "&" them
51+
var (
52+
iptablesBackend = "iptables"
53+
nftablesBackend = "nftables"
54+
)
55+
4956
// PortMapEntry corresponds to a single entry in the port_mappings argument,
5057
// see CONVENTIONS.md
5158
type PortMapEntry struct {
@@ -61,6 +68,7 @@ type PortMapConf struct {
6168
mapper PortMapper
6269

6370
// Generic config
71+
Backend *string `json:"backend,omitempty"`
6472
SNAT *bool `json:"snat,omitempty"`
6573
ConditionsV4 *[]string `json:"conditionsV4"`
6674
ConditionsV6 *[]string `json:"conditionsV6"`
@@ -240,6 +248,21 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, *current.Result, er
240248
return nil, nil, fmt.Errorf("MasqMarkBit must be between 0 and 31")
241249
}
242250

251+
err := ensureBackend(&conf)
252+
if err != nil {
253+
return nil, nil, err
254+
}
255+
switch *conf.Backend {
256+
case iptablesBackend:
257+
conf.mapper = &portMapperIPTables{}
258+
259+
case nftablesBackend:
260+
conf.mapper = &portMapperNFTables{}
261+
262+
default:
263+
return nil, nil, fmt.Errorf("unrecognized backend %q", *conf.Backend)
264+
}
265+
243266
// Reject invalid port numbers
244267
for _, pm := range conf.RuntimeConfig.PortMaps {
245268
if pm.ContainerPort <= 0 {
@@ -279,3 +302,58 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, *current.Result, er
279302

280303
return &conf, result, nil
281304
}
305+
306+
// ensureBackend validates and/or sets conf.Backend
307+
func ensureBackend(conf *PortMapConf) error {
308+
backendConfig := make(map[string][]string)
309+
310+
if conf.ExternalSetMarkChain != nil {
311+
backendConfig[iptablesBackend] = append(backendConfig[iptablesBackend], "externalSetMarkChain")
312+
}
313+
if conditionsBackend := detectBackendOfConditions(conf.ConditionsV4); conditionsBackend != "" {
314+
backendConfig[conditionsBackend] = append(backendConfig[conditionsBackend], "conditionsV4")
315+
}
316+
if conditionsBackend := detectBackendOfConditions(conf.ConditionsV6); conditionsBackend != "" {
317+
backendConfig[conditionsBackend] = append(backendConfig[conditionsBackend], "conditionsV6")
318+
}
319+
320+
// If backend wasn't requested explicitly, default to iptables, unless it is not
321+
// available (and nftables is). FIXME: flip this default at some point.
322+
if conf.Backend == nil {
323+
if !utils.SupportsIPTables() && utils.SupportsNFTables() {
324+
conf.Backend = &nftablesBackend
325+
} else {
326+
conf.Backend = &iptablesBackend
327+
}
328+
}
329+
330+
// Make sure we dont have config for the wrong backend
331+
var wrongBackend string
332+
if *conf.Backend == iptablesBackend {
333+
wrongBackend = nftablesBackend
334+
} else {
335+
wrongBackend = iptablesBackend
336+
}
337+
if len(backendConfig[wrongBackend]) > 0 {
338+
return fmt.Errorf("%s backend was requested but configuration contains %s-specific options %v", *conf.Backend, wrongBackend, backendConfig[wrongBackend])
339+
}
340+
341+
// OK
342+
return nil
343+
}
344+
345+
// detectBackendOfConditions returns "iptables" if conditions contains iptables
346+
// conditions, "nftables" if it contains nftables conditions, and "" if it is empty.
347+
func detectBackendOfConditions(conditions *[]string) string {
348+
if conditions == nil || len(*conditions) == 0 || (*conditions)[0] == "" {
349+
return ""
350+
}
351+
352+
// The first token of any iptables condition would start with a hyphen (e.g. "-d",
353+
// "--sport", "-m"). No nftables condition would start that way. (An nftables
354+
// condition might include a negative number, but not as the first token.)
355+
if (*conditions)[0][0] == '-' {
356+
return iptablesBackend
357+
}
358+
return nftablesBackend
359+
}

0 commit comments

Comments
 (0)