From a55fede2d47fa001ebea650c4d4adb2bce48e1cd Mon Sep 17 00:00:00 2001 From: Rob Murray Date: Wed, 2 Jul 2025 17:59:11 +0100 Subject: [PATCH] Pass context to nftables functions Signed-off-by: Rob Murray --- .../bridge/internal/nftabler/nftabler.go | 34 +++---- .../drivers/bridge/internal/nftabler/wsl2.go | 5 +- .../internal/nftables/nftables_linux.go | 66 ++++++++----- .../internal/nftables/nftables_linux_test.go | 97 ++++++++++--------- libnetwork/resolver_unix.go | 12 +-- 5 files changed, 118 insertions(+), 96 deletions(-) diff --git a/libnetwork/drivers/bridge/internal/nftabler/nftabler.go b/libnetwork/drivers/bridge/internal/nftabler/nftabler.go index 447cb9c166..cefec25e09 100644 --- a/libnetwork/drivers/bridge/internal/nftabler/nftabler.go +++ b/libnetwork/drivers/bridge/internal/nftabler/nftabler.go @@ -81,7 +81,7 @@ func (nft *nftabler) getTable(ipv firewaller.IPVersion) nftables.TableRef { func (nft *nftabler) FilterForwardDrop(ctx context.Context, ipv firewaller.IPVersion) error { table := nft.getTable(ipv) - if err := table.Chain(forwardChain).SetPolicy("drop"); err != nil { + if err := table.Chain(ctx, forwardChain).SetPolicy("drop"); err != nil { return err } return nftApply(ctx, table) @@ -104,7 +104,7 @@ func (nft *nftabler) init(ctx context.Context, family nftables.Family) (nftables // So, packets that aren't related to docker don't need to traverse any per-network filter forward // rules - and packets that are entering or leaving docker networks only need to traverse rules // related to those networks. - fwdChain, err := table.BaseChain(forwardChain, + fwdChain, err := table.BaseChain(ctx, forwardChain, nftables.BaseChainTypeFilter, nftables.BaseChainHookForward, nftables.BaseChainPriorityFilter) @@ -112,51 +112,51 @@ func (nft *nftabler) init(ctx context.Context, family nftables.Family) (nftables return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err) } // Instantiate the verdict maps and add the jumps. - _ = table.InterfaceVMap(filtFwdInVMap) - if err := fwdChain.AppendRule(initialRuleGroup, "oifname vmap @"+filtFwdInVMap); err != nil { + _ = table.InterfaceVMap(ctx, filtFwdInVMap) + if err := fwdChain.AppendRule(ctx, initialRuleGroup, "oifname vmap @"+filtFwdInVMap); err != nil { return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err) } - _ = table.InterfaceVMap(filtFwdOutVMap) - if err := fwdChain.AppendRule(initialRuleGroup, "iifname vmap @"+filtFwdOutVMap); err != nil { + _ = table.InterfaceVMap(ctx, filtFwdOutVMap) + if err := fwdChain.AppendRule(ctx, initialRuleGroup, "iifname vmap @"+filtFwdOutVMap); err != nil { return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err) } // Set up the NAT postrouting base chain. // // Like the filter-forward chain, its only rules are jumps to network-specific ingress and egress chains. - natPostRtChain, err := table.BaseChain(postroutingChain, + natPostRtChain, err := table.BaseChain(ctx, postroutingChain, nftables.BaseChainTypeNAT, nftables.BaseChainHookPostrouting, nftables.BaseChainPrioritySrcNAT) if err != nil { return nftables.TableRef{}, err } - _ = table.InterfaceVMap(natPostroutingOutVMap) - if err := natPostRtChain.AppendRule(initialRuleGroup, "iifname vmap @"+natPostroutingOutVMap); err != nil { + _ = table.InterfaceVMap(ctx, natPostroutingOutVMap) + if err := natPostRtChain.AppendRule(ctx, initialRuleGroup, "iifname vmap @"+natPostroutingOutVMap); err != nil { return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err) } - _ = table.InterfaceVMap(natPostroutingInVMap) - if err := natPostRtChain.AppendRule(initialRuleGroup, "oifname vmap @"+natPostroutingInVMap); err != nil { + _ = table.InterfaceVMap(ctx, natPostroutingInVMap) + if err := natPostRtChain.AppendRule(ctx, initialRuleGroup, "oifname vmap @"+natPostroutingInVMap); err != nil { return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err) } // Instantiate natChain, for the NAT prerouting and output base chains to jump to. - _ = table.Chain(natChain) + _ = table.Chain(ctx, natChain) // Set up the NAT prerouting base chain. - natPreRtChain, err := table.BaseChain(preroutingChain, + natPreRtChain, err := table.BaseChain(ctx, preroutingChain, nftables.BaseChainTypeNAT, nftables.BaseChainHookPrerouting, nftables.BaseChainPriorityDstNAT) if err != nil { return nftables.TableRef{}, err } - if err := natPreRtChain.AppendRule(initialRuleGroup, "fib daddr type local counter jump "+natChain); err != nil { + if err := natPreRtChain.AppendRule(ctx, initialRuleGroup, "fib daddr type local counter jump "+natChain); err != nil { return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err) } // Set up the NAT output base chain - natOutputChain, err := table.BaseChain(outputChain, + natOutputChain, err := table.BaseChain(ctx, outputChain, nftables.BaseChainTypeNAT, nftables.BaseChainHookOutput, nftables.BaseChainPriorityDstNAT) @@ -172,12 +172,12 @@ func (nft *nftabler) init(ctx context.Context, family nftables.Family) (nftables skipLoopback = "ip6 daddr != ::1 " } } - if err := natOutputChain.AppendRule(initialRuleGroup, skipLoopback+"fib daddr type local counter jump "+natChain); err != nil { + if err := natOutputChain.AppendRule(ctx, initialRuleGroup, skipLoopback+"fib daddr type local counter jump "+natChain); err != nil { return nftables.TableRef{}, fmt.Errorf("initialising nftables: %w", err) } // Set up the raw prerouting base chain - if _, err := table.BaseChain(rawPreroutingChain, + if _, err := table.BaseChain(ctx, rawPreroutingChain, nftables.BaseChainTypeFilter, nftables.BaseChainHookPrerouting, nftables.BaseChainPriorityRaw); err != nil { diff --git a/libnetwork/drivers/bridge/internal/nftabler/wsl2.go b/libnetwork/drivers/bridge/internal/nftabler/wsl2.go index 448ea8c5f3..2a86b1b792 100644 --- a/libnetwork/drivers/bridge/internal/nftabler/wsl2.go +++ b/libnetwork/drivers/bridge/internal/nftabler/wsl2.go @@ -8,7 +8,7 @@ import ( "github.com/docker/docker/libnetwork/internal/nftables" ) -// mirroredWSL2Workaround adds IPv4 NAT rule if docker's host Linux appears to +// mirroredWSL2Workaround adds IPv4 NAT rule if docker's host Linux appears to // be a guest running under WSL2 in with mirrored mode networking. // https://learn.microsoft.com/en-us/windows/wsl/networking#mirrored-mode-networking // @@ -44,5 +44,6 @@ func mirroredWSL2Workaround(ctx context.Context, table nftables.TableRef) error if table.Family() != nftables.IPv4 { return nil } - return table.Chain(natChain).AppendRule(initialRuleGroup, `iifname "loopback0" ip daddr 127.0.0.0/8 counter return`) + return table.Chain(ctx, natChain).AppendRule(ctx, + initialRuleGroup, `iifname "loopback0" ip daddr 127.0.0.0/8 counter return`) } diff --git a/libnetwork/internal/nftables/nftables_linux.go b/libnetwork/internal/nftables/nftables_linux.go index 98af625ad4..4b27fd3818 100644 --- a/libnetwork/internal/nftables/nftables_linux.go +++ b/libnetwork/internal/nftables/nftables_linux.go @@ -408,7 +408,7 @@ type ChainRef struct { // It is an error to create a base chain that already exists. // If the underlying chain already exists, it will be flushed by the // next [TableRef.Apply] before new rules are added. -func (t TableRef) BaseChain(name string, chainType BaseChainType, hook BaseChainHook, priority int) (ChainRef, error) { +func (t TableRef) BaseChain(ctx context.Context, name string, chainType BaseChainType, hook BaseChainHook, priority int) (ChainRef, error) { if _, ok := t.t.Chains[name]; ok { return ChainRef{}, fmt.Errorf("chain %q already exists", name) } @@ -423,7 +423,7 @@ func (t TableRef) BaseChain(name string, chainType BaseChainType, hook BaseChain ruleGroups: map[RuleGroup][]string{}, } t.t.Chains[name] = c - log.G(context.TODO()).WithFields(log.Fields{ + log.G(ctx).WithFields(log.Fields{ "family": t.t.Family, "table": t.t.Name, "chain": name, @@ -442,7 +442,7 @@ func (t TableRef) BaseChain(name string, chainType BaseChainType, hook BaseChain // // If a new [ChainRef] is created and the underlying chain already exists, it // will be flushed by the next [TableRef.Apply] before new rules are added. -func (t TableRef) Chain(name string) ChainRef { +func (t TableRef) Chain(ctx context.Context, name string) ChainRef { c, ok := t.t.Chains[name] if !ok { c = &chain{ @@ -453,7 +453,7 @@ func (t TableRef) Chain(name string) ChainRef { } t.t.Chains[name] = c } - log.G(context.TODO()).WithFields(log.Fields{ + log.G(ctx).WithFields(log.Fields{ "family": t.t.Family, "table": t.t.Name, "chain": name, @@ -462,14 +462,14 @@ func (t TableRef) Chain(name string) ChainRef { } // ChainUpdateFunc is a function that can add rules to a chain, or remove rules from it. -type ChainUpdateFunc func(RuleGroup, string, ...interface{}) error +type ChainUpdateFunc func(context.Context, RuleGroup, string, ...interface{}) error // ChainUpdateFunc returns a [ChainUpdateFunc] to add rules to the named chain if // enable is true, or to remove rules from the chain if enable is false. // (Written as a convenience function to ease migration of iptables functions // originally written with an enable flag.) -func (t TableRef) ChainUpdateFunc(name string, enable bool) ChainUpdateFunc { - c := t.Chain(name) +func (t TableRef) ChainUpdateFunc(ctx context.Context, name string, enable bool) ChainUpdateFunc { + c := t.Chain(ctx, name) if enable { return c.AppendRule } @@ -477,14 +477,14 @@ func (t TableRef) ChainUpdateFunc(name string, enable bool) ChainUpdateFunc { } // DeleteChain deletes a chain. It is an error to delete a chain that does not exist. -func (t TableRef) DeleteChain(name string) error { +func (t TableRef) DeleteChain(ctx context.Context, name string) error { if _, ok := t.t.Chains[name]; !ok { return fmt.Errorf("chain %q does not exist", name) } delete(t.t.Chains, name) t.t.DeleteChainCommands = append(t.t.DeleteChainCommands, fmt.Sprintf("delete chain %s %s %s", t.t.Family, t.t.Name, name)) - log.G(context.TODO()).WithFields(log.Fields{ + log.G(ctx).WithFields(log.Fields{ "family": t.t.Family, "table": t.t.Name, "chain": name, @@ -504,7 +504,7 @@ func (c ChainRef) SetPolicy(policy string) error { } // AppendRule appends a rule to a [RuleGroup] in a [ChainRef]. -func (c ChainRef) AppendRule(group RuleGroup, rule string, args ...interface{}) error { +func (c ChainRef) AppendRule(ctx context.Context, group RuleGroup, rule string, args ...interface{}) error { if len(args) > 0 { rule = fmt.Sprintf(rule, args...) } @@ -513,7 +513,7 @@ func (c ChainRef) AppendRule(group RuleGroup, rule string, args ...interface{}) } c.c.ruleGroups[group] = append(c.c.ruleGroups[group], rule) c.c.Dirty = true - log.G(context.TODO()).WithFields(log.Fields{ + log.G(ctx).WithFields(log.Fields{ "family": c.c.table.Family, "table": c.c.table.Name, "chain": c.c.Name, @@ -523,10 +523,18 @@ func (c ChainRef) AppendRule(group RuleGroup, rule string, args ...interface{}) return nil } +// AppendRuleCf calls AppendRule and returns a cleanup function or an error. +func (c ChainRef) AppendRuleCf(ctx context.Context, group RuleGroup, rule string, args ...interface{}) (func(context.Context) error, error) { + if err := c.AppendRule(ctx, group, rule, args...); err != nil { + return nil, err + } + return func(ctx context.Context) error { return c.DeleteRule(ctx, group, rule, args...) }, nil +} + // DeleteRule deletes a rule from a [RuleGroup] in a [ChainRef]. It is an error // to delete from a group that does not exist, or to delete a rule that does not // exist. -func (c ChainRef) DeleteRule(group RuleGroup, rule string, args ...interface{}) error { +func (c ChainRef) DeleteRule(ctx context.Context, group RuleGroup, rule string, args ...interface{}) error { if len(args) > 0 { rule = fmt.Sprintf(rule, args...) } @@ -540,7 +548,7 @@ func (c ChainRef) DeleteRule(group RuleGroup, rule string, args ...interface{}) return fmt.Errorf("rule %q does not exist", rule) } c.c.Dirty = true - log.G(context.TODO()).WithFields(log.Fields{ + log.G(ctx).WithFields(log.Fields{ "family": c.c.table.Family, "table": c.c.table.Name, "chain": c.c.Name, @@ -578,7 +586,7 @@ type VMapRef struct { // // If a [VMapRef] is created and the underlying map already exists, it will be flushed // by the next [TableRef.Apply] before new elements are added. -func (t TableRef) InterfaceVMap(name string) VMapRef { +func (t TableRef) InterfaceVMap(ctx context.Context, name string) VMapRef { if vmap, ok := t.t.VMaps[name]; ok { return VMapRef{vmap} } @@ -592,7 +600,7 @@ func (t TableRef) InterfaceVMap(name string) VMapRef { Dirty: true, } t.t.VMaps[name] = vmap - log.G(context.TODO()).WithFields(log.Fields{ + log.G(ctx).WithFields(log.Fields{ "family": t.t.Family, "table": t.t.Name, "vmap": name, @@ -602,13 +610,13 @@ func (t TableRef) InterfaceVMap(name string) VMapRef { // AddElement adds an element to a verdict map. The caller must ensure the key has // the correct type. It is an error to add a key that already exists. -func (v VMapRef) AddElement(key string, verdict string) error { +func (v VMapRef) AddElement(ctx context.Context, key string, verdict string) error { if _, ok := v.v.Elements[key]; ok { return fmt.Errorf("verdict map already contains element %q", key) } v.v.Elements[key] = verdict v.v.AddedElements[key] = verdict - log.G(context.TODO()).WithFields(log.Fields{ + log.G(ctx).WithFields(log.Fields{ "family": v.v.table.Family, "table": v.v.table.Name, "vmap": v.v.Name, @@ -618,15 +626,23 @@ func (v VMapRef) AddElement(key string, verdict string) error { return nil } +// AddElementCf calls AddElement and returns a cleanup function or an error. +func (v VMapRef) AddElementCf(ctx context.Context, key string, verdict string) (func(context.Context) error, error) { + if err := v.AddElement(ctx, key, verdict); err != nil { + return nil, err + } + return func(ctx context.Context) error { return v.DeleteElement(ctx, key) }, nil +} + // DeleteElement deletes an element from a verdict map. It is an error to delete // an element that does not exist. -func (v VMapRef) DeleteElement(key string) error { +func (v VMapRef) DeleteElement(ctx context.Context, key string) error { if _, ok := v.v.Elements[key]; !ok { return fmt.Errorf("verdict map does not contain element %q", key) } delete(v.v.Elements, key) v.v.DeletedElements[key] = struct{}{} - log.G(context.TODO()).WithFields(log.Fields{ + log.G(ctx).WithFields(log.Fields{ "family": v.v.table.Family, "table": v.v.table.Name, "vmap": v.v.Name, @@ -666,7 +682,7 @@ type SetRef struct { // change if we need an "inet" table.) // // See https://wiki.nftables.org/wiki-nftables/index.php/Sets#Named_sets -func (t TableRef) PrefixSet(name string) SetRef { +func (t TableRef) PrefixSet(ctx context.Context, name string) SetRef { if s, ok := t.t.Sets[name]; ok { return SetRef{s} } @@ -684,7 +700,7 @@ func (t TableRef) PrefixSet(name string) SetRef { s.ElementType = nftTypeIPv6Addr } t.t.Sets[name] = s - log.G(context.TODO()).WithFields(log.Fields{ + log.G(ctx).WithFields(log.Fields{ "family": t.t.Family, "table": t.t.Name, "set": name, @@ -695,13 +711,13 @@ func (t TableRef) PrefixSet(name string) SetRef { // AddElement adds an element to a set. It is the caller's responsibility to make sure // the element has the correct type. It is an error to add an element that is already // in the set. -func (s SetRef) AddElement(element string) error { +func (s SetRef) AddElement(ctx context.Context, element string) error { if _, ok := s.s.Elements[element]; ok { return fmt.Errorf("set already contains element %q", element) } s.s.Elements[element] = struct{}{} s.s.AddedElements[element] = struct{}{} - log.G(context.TODO()).WithFields(log.Fields{ + log.G(ctx).WithFields(log.Fields{ "family": s.s.table.Family, "table": s.s.table.Name, "set": s.s.Name, @@ -712,13 +728,13 @@ func (s SetRef) AddElement(element string) error { // DeleteElement deletes an element from the set. It is an error to delete an // element that is not in the set. -func (s SetRef) DeleteElement(element string) error { +func (s SetRef) DeleteElement(ctx context.Context, element string) error { if _, ok := s.s.Elements[element]; !ok { return fmt.Errorf("set does not contain element %q", element) } delete(s.s.Elements, element) s.s.DeletedElements[element] = struct{}{} - log.G(context.TODO()).WithFields(log.Fields{ + log.G(ctx).WithFields(log.Fields{ "family": s.s.table.Family, "table": s.s.table.Name, "set": s.s.Name, diff --git a/libnetwork/internal/nftables/nftables_linux_test.go b/libnetwork/internal/nftables/nftables_linux_test.go index e1caa44a94..9eb38869ab 100644 --- a/libnetwork/internal/nftables/nftables_linux_test.go +++ b/libnetwork/internal/nftables/nftables_linux_test.go @@ -58,6 +58,7 @@ func TestTable(t *testing.T) { func TestChain(t *testing.T) { defer testSetup(t)() + ctx := context.Background() // Create a table. tbl, err := NewTable(IPv4, "this_is_a_table") @@ -65,68 +66,68 @@ func TestChain(t *testing.T) { // Create a base chain. const bcName = "this_is_a_base_chain" - bc1, err := tbl.BaseChain(bcName, BaseChainTypeFilter, BaseChainHookForward, BaseChainPriorityFilter+10) + bc1, err := tbl.BaseChain(ctx, bcName, BaseChainTypeFilter, BaseChainHookForward, BaseChainPriorityFilter+10) assert.NilError(t, err) // Check that it's an error to add a new base chain with the same name. - _, err = tbl.BaseChain(bcName, BaseChainTypeNAT, BaseChainHookPrerouting, BaseChainPriorityDstNAT) + _, err = tbl.BaseChain(ctx, bcName, BaseChainTypeNAT, BaseChainHookPrerouting, BaseChainPriorityDstNAT) assert.Check(t, is.ErrorContains(err, "already exists")) // Add a rule. - err = bc1.AppendRule(0, "counter") + err = bc1.AppendRule(ctx, 0, "counter") assert.NilError(t, err) // Add a regular chain. const regularChainName = "this_is_a_regular_chain" - _ = tbl.Chain(regularChainName) + _ = tbl.Chain(ctx, regularChainName) // Add a rule to the regular chain, use string formatting and a func retrieved // from the table. - f := tbl.ChainUpdateFunc(regularChainName, true) - err = f(0, "counter %s", "accept") + f := tbl.ChainUpdateFunc(ctx, regularChainName, true) + err = f(ctx, 0, "counter %s", "accept") assert.Check(t, err) // Fetch the base chain by name. - bc1 = tbl.Chain(bcName) + bc1 = tbl.Chain(ctx, bcName) // Add another rule to the base chain, using the newly-retrieved handle. - err = bc1.AppendRule(0, "jump %s", regularChainName) + err = bc1.AppendRule(ctx, 0, "jump %s", regularChainName) assert.Check(t, err) // Update nftables and check what happened. applyAndCheck(t, tbl, t.Name()+"_created.golden") // Delete a rule from the base chain. - f = tbl.ChainUpdateFunc(bcName, false) - err = f(0, "counter") + f = tbl.ChainUpdateFunc(ctx, bcName, false) + err = f(ctx, 0, "counter") assert.Check(t, err) // Check it's an error to delete that rule again. This time, call the delete // function directly on a newly retrieved handle. - err = tbl.Chain(bcName).DeleteRule(0, "counter") + err = tbl.Chain(ctx, bcName).DeleteRule(ctx, 0, "counter") assert.Check(t, is.ErrorContains(err, "does not exist")) // Update the base chain's policy. - err = tbl.Chain(bcName).SetPolicy("drop") + err = tbl.Chain(ctx, bcName).SetPolicy("drop") assert.Check(t, err) // Check it's an error to set a policy on a regular chain. - err = tbl.Chain(regularChainName).SetPolicy("drop") + err = tbl.Chain(ctx, regularChainName).SetPolicy("drop") assert.Check(t, is.ErrorContains(err, "not a base chain")) // Update nftables and check what happened. applyAndCheck(t, tbl, t.Name()+"_modified.golden") // Delete the base chain. - err = tbl.DeleteChain(bcName) + err = tbl.DeleteChain(ctx, bcName) assert.Check(t, err) // Delete the regular chain. - err = tbl.DeleteChain(regularChainName) + err = tbl.DeleteChain(ctx, regularChainName) assert.Check(t, err) // Check that it's an error to delete it again. - err = tbl.DeleteChain(regularChainName) + err = tbl.DeleteChain(ctx, regularChainName) assert.Check(t, is.ErrorContains(err, "does not exist")) // Update nftables and check what happened. @@ -135,19 +136,20 @@ func TestChain(t *testing.T) { func TestChainRuleGroups(t *testing.T) { defer testSetup(t)() + ctx := context.Background() tbl, err := NewTable(IPv4, "testtable") assert.NilError(t, err) - c := tbl.Chain("testchain") - err = c.AppendRule(100, "hello100") + c := tbl.Chain(ctx, "testchain") + err = c.AppendRule(ctx, 100, "hello100") assert.Check(t, err) - err = c.AppendRule(200, "hello200") + err = c.AppendRule(ctx, 200, "hello200") assert.Check(t, err) - err = c.AppendRule(100, "hello101") + err = c.AppendRule(ctx, 100, "hello101") assert.Check(t, err) - err = c.AppendRule(200, "hello201") + err = c.AppendRule(ctx, 200, "hello201") assert.Check(t, err) - err = c.AppendRule(100, "hello102") + err = c.AppendRule(ctx, 100, "hello102") assert.Check(t, err) assert.Check(t, is.DeepEqual(c.c.Rules(), []string{ @@ -158,6 +160,7 @@ func TestChainRuleGroups(t *testing.T) { func TestVMap(t *testing.T) { defer testSetup(t)() + ctx := context.Background() // Create a table. tbl, err := NewTable(IPv6, "this_is_a_table") @@ -165,32 +168,32 @@ func TestVMap(t *testing.T) { // Create a verdict map. const mapName = "this_is_a_vmap" - m := tbl.InterfaceVMap(mapName) + m := tbl.InterfaceVMap(ctx, mapName) // Add an element. - err = m.AddElement("eth0", "return") + err = m.AddElement(ctx, "eth0", "return") assert.Check(t, err) // Check that it's an error to add the element again. - err = m.AddElement("eth0", "return") + err = m.AddElement(ctx, "eth0", "return") assert.Check(t, is.ErrorContains(err, "already contains element")) // Fetch the existing vmap. - m = tbl.InterfaceVMap(mapName) + m = tbl.InterfaceVMap(ctx, mapName) // Add another element. - err = m.AddElement("eth1", "drop") + err = m.AddElement(ctx, "eth1", "drop") assert.Check(t, err) // Update nftables and check what happened. applyAndCheck(t, tbl, t.Name()+"_created.golden") // Delete an element. - err = m.DeleteElement("eth1") + err = m.DeleteElement(ctx, "eth1") assert.Check(t, err) // Check it's an error to delete it again. - err = m.DeleteElement("eth1") + err = m.DeleteElement(ctx, "eth1") assert.Check(t, is.ErrorContains(err, "does not contain element")) // Update nftables and check what happened. @@ -199,6 +202,7 @@ func TestVMap(t *testing.T) { func TestSet(t *testing.T) { defer testSetup(t)() + ctx := context.Background() // Create v4 and v6 tables. tbl4, err := NewTable(IPv4, "table4") @@ -207,19 +211,19 @@ func TestSet(t *testing.T) { assert.NilError(t, err) // Create a set in each table. - s4 := tbl4.PrefixSet("set4") - s6 := tbl6.PrefixSet("set6") + s4 := tbl4.PrefixSet(ctx, "set4") + s6 := tbl6.PrefixSet(ctx, "set6") // Add elements to each set. - err = s4.AddElement("192.0.2.1/24") + err = s4.AddElement(ctx, "192.0.2.1/24") assert.Check(t, err) - err = s6.AddElement("2001:db8::1/64") + err = s6.AddElement(ctx, "2001:db8::1/64") assert.Check(t, err) // Check it's an error to add those elements again. - err = s4.AddElement("192.0.2.1/24") + err = s4.AddElement(ctx, "192.0.2.1/24") assert.Check(t, is.ErrorContains(err, "already contains element")) - err = s6.AddElement("2001:db8::1/64") + err = s6.AddElement(ctx, "2001:db8::1/64") assert.Check(t, is.ErrorContains(err, "already contains element")) // Update nftables and check what happened. @@ -227,15 +231,15 @@ func TestSet(t *testing.T) { applyAndCheck(t, tbl6, t.Name()+"_created46.golden") // Delete elements. - err = s4.DeleteElement("192.0.2.1/24") + err = s4.DeleteElement(ctx, "192.0.2.1/24") assert.Check(t, err) - err = s6.DeleteElement("2001:db8::1/64") + err = s6.DeleteElement(ctx, "2001:db8::1/64") assert.Check(t, err) // Check it's an error to delete those elements again. - err = s4.DeleteElement("192.0.2.1/24") + err = s4.DeleteElement(ctx, "192.0.2.1/24") assert.Check(t, is.ErrorContains(err, "does not contain element")) - err = s6.DeleteElement("2001:db8::1/64") + err = s6.DeleteElement(ctx, "2001:db8::1/64") assert.Check(t, is.ErrorContains(err, "does not contain element")) // Update nftables and check what happened. @@ -245,21 +249,22 @@ func TestSet(t *testing.T) { func TestReload(t *testing.T) { defer testSetup(t)() + ctx := context.Background() // Create a table with some stuff in it. const tableName = "this_is_a_table" tbl, err := NewTable(IPv4, tableName) assert.NilError(t, err) - bc, err := tbl.BaseChain("a_base_chain", BaseChainTypeFilter, BaseChainHookForward, BaseChainPriorityFilter) + bc, err := tbl.BaseChain(ctx, "a_base_chain", BaseChainTypeFilter, BaseChainHookForward, BaseChainPriorityFilter) assert.NilError(t, err) - err = bc.AppendRule(0, "counter") + err = bc.AppendRule(ctx, 0, "counter") assert.NilError(t, err) - m := tbl.InterfaceVMap("this_is_a_vmap") - err = m.AddElement("eth0", "return") + m := tbl.InterfaceVMap(ctx, "this_is_a_vmap") + err = m.AddElement(ctx, "eth0", "return") assert.Check(t, err) - err = m.AddElement("eth1", "return") + err = m.AddElement(ctx, "eth1", "return") assert.Check(t, err) - err = tbl.PrefixSet("set4").AddElement("192.0.2.0/24") + err = tbl.PrefixSet(ctx, "set4").AddElement(ctx, "192.0.2.0/24") assert.Check(t, err) applyAndCheck(t, tbl, t.Name()+"_created.golden") @@ -284,7 +289,7 @@ func TestReload(t *testing.T) { // Check implicit/recovery reload - only deleting something that's gone missing // from a vmap/set will trigger this. - err = m.DeleteElement("eth1") + err = m.DeleteElement(ctx, "eth1") assert.Check(t, err) applyAndCheck(t, tbl, t.Name()+"_recovered.golden") } diff --git a/libnetwork/resolver_unix.go b/libnetwork/resolver_unix.go index 7d007f1985..135f48528a 100644 --- a/libnetwork/resolver_unix.go +++ b/libnetwork/resolver_unix.go @@ -98,25 +98,25 @@ func (r *Resolver) setupNftablesNAT(ctx context.Context, laddr, ltcpaddr, resolv return err } - dnatChain, err := table.BaseChain("dns-dnat", nftables.BaseChainTypeNAT, nftables.BaseChainHookOutput, nftables.BaseChainPriorityDstNAT) + dnatChain, err := table.BaseChain(ctx, "dns-dnat", nftables.BaseChainTypeNAT, nftables.BaseChainHookOutput, nftables.BaseChainPriorityDstNAT) if err != nil { return err } - if err := dnatChain.AppendRule(0, "ip daddr %s udp dport %s counter dnat to %s", resolverIP, dnsPort, laddr); err != nil { + if err := dnatChain.AppendRule(ctx, 0, "ip daddr %s udp dport %s counter dnat to %s", resolverIP, dnsPort, laddr); err != nil { return err } - if err := dnatChain.AppendRule(0, "ip daddr %s tcp dport %s counter dnat to %s", resolverIP, dnsPort, ltcpaddr); err != nil { + if err := dnatChain.AppendRule(ctx, 0, "ip daddr %s tcp dport %s counter dnat to %s", resolverIP, dnsPort, ltcpaddr); err != nil { return err } - snatChain, err := table.BaseChain("dns-snat", nftables.BaseChainTypeNAT, nftables.BaseChainHookPostrouting, nftables.BaseChainPrioritySrcNAT) + snatChain, err := table.BaseChain(ctx, "dns-snat", nftables.BaseChainTypeNAT, nftables.BaseChainHookPostrouting, nftables.BaseChainPrioritySrcNAT) if err != nil { return err } - if err := snatChain.AppendRule(0, "ip saddr %s udp sport %s counter snat to :%s", resolverIP, ipPort, dnsPort); err != nil { + if err := snatChain.AppendRule(ctx, 0, "ip saddr %s udp sport %s counter snat to :%s", resolverIP, ipPort, dnsPort); err != nil { return err } - if err := snatChain.AppendRule(0, "ip saddr %s tcp sport %s counter snat to :%s", resolverIP, tcpPort, dnsPort); err != nil { + if err := snatChain.AppendRule(ctx, 0, "ip saddr %s tcp sport %s counter snat to :%s", resolverIP, tcpPort, dnsPort); err != nil { return err }