From de71462b9748458c1ea10ec379288590fe447d28 Mon Sep 17 00:00:00 2001 From: Cory Snider Date: Fri, 26 Jun 2026 17:25:22 -0400 Subject: [PATCH] d/libn/i/nftables: add fluent chain builder API With most of the dynamism of nftables rulesets being powered by named maps and sets, the rules of a chain are often initialized when the chain is added, and never touched again. Add a fluent API for adding the creation of a chain and all its rules to a modifier without having to repeat the chain name for each rule. Signed-off-by: Cory Snider --- .../internal/nftables/fluentapi_linux.go | 30 +++++++++++++++++++ .../internal/nftables/nftables_linux.go | 6 +++- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 daemon/libnetwork/internal/nftables/fluentapi_linux.go diff --git a/daemon/libnetwork/internal/nftables/fluentapi_linux.go b/daemon/libnetwork/internal/nftables/fluentapi_linux.go new file mode 100644 index 0000000000..fec8c3ee1c --- /dev/null +++ b/daemon/libnetwork/internal/nftables/fluentapi_linux.go @@ -0,0 +1,30 @@ +package nftables + +type chainBuilder struct { + chain string + tm *Modifier +} + +func (b BaseChain) Builder() chainBuilder { + tm := &Modifier{} + tm.create(b, 1) + return chainBuilder{chain: b.Name, tm: tm} +} + +func (c Chain) Builder() chainBuilder { + tm := &Modifier{} + tm.create(c, 1) + return chainBuilder{chain: c.Name, tm: tm} +} + +func (b chainBuilder) Rule(rule ...string) chainBuilder { + b.tm.create(Rule{ + Chain: b.chain, + Rule: rule, + }, 1) + return b +} + +func (b chainBuilder) Create(tm *Modifier) { + tm.cmds = append(tm.cmds, b.tm.cmds...) +} diff --git a/daemon/libnetwork/internal/nftables/nftables_linux.go b/daemon/libnetwork/internal/nftables/nftables_linux.go index 78236ad2d7..9c4b9261c6 100644 --- a/daemon/libnetwork/internal/nftables/nftables_linux.go +++ b/daemon/libnetwork/internal/nftables/nftables_linux.go @@ -490,7 +490,11 @@ type Modifier struct { // Create enqueues creation of object o, to be applied by tm.Apply. func (tm *Modifier) Create(o Obj) { - _, f, l, _ := runtime.Caller(1) + tm.create(o, 1) +} + +func (tm *Modifier) create(o Obj, skipFrames int) { + _, f, l, _ := runtime.Caller(skipFrames + 1) tm.cmds = append(tm.cmds, command{ obj: o, callerFile: f,