diff --git a/daemon/libnetwork/drivers/bridge/internal/nftabler/cleaner.go b/daemon/libnetwork/drivers/bridge/internal/nftabler/cleaner.go index c57c36d654..94aa9cefe4 100644 --- a/daemon/libnetwork/drivers/bridge/internal/nftabler/cleaner.go +++ b/daemon/libnetwork/drivers/bridge/internal/nftabler/cleaner.go @@ -3,6 +3,7 @@ package nftabler import ( + "bytes" "context" "os/exec" @@ -16,21 +17,28 @@ import ( // after switching to a different Firewaller implementation. func Cleanup(ctx context.Context, config firewaller.Config) { if config.IPv4 { - if err := exec.Command("nft", "delete", "table", string(nftables.IPv4), dockerTable).Run(); err != nil { - log.G(ctx).WithError(err).Info("Deleting nftables IPv4 rules") - } else { - log.G(ctx).Info("Deleted nftables IPv4 rules") - } + tryCleanup(ctx, nftables.IPv4, "IPv4") } if config.IPv6 { - if err := exec.Command("nft", "delete", "table", string(nftables.IPv6), dockerTable).Run(); err != nil { - log.G(ctx).WithError(err).Info("Deleting nftables IPv6 rules") - } else { - log.G(ctx).Info("Deleted nftables IPv6 rules") - } + tryCleanup(ctx, nftables.IPv6, "IPv6") } } +func tryCleanup(ctx context.Context, family nftables.Family, label string) { + cmd := exec.CommandContext(ctx, "nft", "delete", "table", string(family), dockerTable) + out, err := cmd.CombinedOutput() + if err != nil { + // May not exist ("Error: Could not process rule: No such file or directory") + log.G(ctx).WithFields(log.Fields{ + "error": err, + "output": string(bytes.TrimRight(out, "\n ^")), // remove "^^^^^" added in nft's error message. + }).Info("Deleting nftables " + label + " rules") + return + } + + log.G(ctx).Info("Deleted nftables " + label + " rules") +} + func (nft *Nftabler) SetFirewallCleaner(fc firewaller.FirewallCleaner) { nft.cleaner = fc }