@@ -37,6 +37,7 @@ import (
37
37
"github.com/containernetworking/cni/pkg/types"
38
38
current "github.com/containernetworking/cni/pkg/types/100"
39
39
"github.com/containernetworking/cni/pkg/version"
40
+ "github.com/containernetworking/plugins/pkg/utils"
40
41
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
41
42
)
42
43
@@ -46,6 +47,12 @@ type PortMapper interface {
46
47
unforwardPorts (config * PortMapConf ) error
47
48
}
48
49
50
+ // These are vars rather than consts so we can "&" them
51
+ var (
52
+ iptablesBackend = "iptables"
53
+ nftablesBackend = "nftables"
54
+ )
55
+
49
56
// PortMapEntry corresponds to a single entry in the port_mappings argument,
50
57
// see CONVENTIONS.md
51
58
type PortMapEntry struct {
@@ -61,6 +68,7 @@ type PortMapConf struct {
61
68
mapper PortMapper
62
69
63
70
// Generic config
71
+ Backend * string `json:"backend,omitempty"`
64
72
SNAT * bool `json:"snat,omitempty"`
65
73
ConditionsV4 * []string `json:"conditionsV4"`
66
74
ConditionsV6 * []string `json:"conditionsV6"`
@@ -240,6 +248,21 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, *current.Result, er
240
248
return nil , nil , fmt .Errorf ("MasqMarkBit must be between 0 and 31" )
241
249
}
242
250
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
+
243
266
// Reject invalid port numbers
244
267
for _ , pm := range conf .RuntimeConfig .PortMaps {
245
268
if pm .ContainerPort <= 0 {
@@ -279,3 +302,58 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, *current.Result, er
279
302
280
303
return & conf , result , nil
281
304
}
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