diff --git a/pkg/util/ebtables/ebtables.go b/pkg/util/ebtables/ebtables.go index 4e88d19e62c..4ff25b0b242 100644 --- a/pkg/util/ebtables/ebtables.go +++ b/pkg/util/ebtables/ebtables.go @@ -43,6 +43,7 @@ type Table string const ( TableNAT Table = "nat" TableFilter Table = "filter" + TableBroute Table = "broute" ) type Chain string @@ -52,6 +53,7 @@ const ( ChainPrerouting Chain = "PREROUTING" ChainOutput Chain = "OUTPUT" ChainInput Chain = "INPUT" + ChainBrouting Chain = "BROUTING" ) type operation string @@ -75,6 +77,8 @@ type Interface interface { // Input args must follow the format and sequence of ebtables list output. Otherwise, EnsureRule will always create // new rules and causing duplicates. EnsureRule(position RulePosition, table Table, chain Chain, args ...string) (bool, error) + // DeleteRule checks if the specified rule is present and, if so, deletes it. + DeleteRule(table Table, chain Chain, args ...string) error // EnsureChain checks if the specified chain is present and, if not, creates it. If the rule existed, return true. EnsureChain(table Table, chain Chain) (bool, error) // DeleteChain deletes the specified chain. If the chain did not exist, return error. @@ -139,6 +143,27 @@ func (runner *runner) EnsureRule(position RulePosition, table Table, chain Chain return exist, nil } +func (runner *runner) DeleteRule(table Table, chain Chain, args ...string) error { + exist := true + fullArgs := makeFullArgs(table, opListChain, chain, fullMac) + out, err := runner.exec.Command(cmdebtables, fullArgs...).CombinedOutput() + if err != nil { + exist = false + } else { + exist = checkIfRuleExists(string(out), args...) + } + + if !exist { + return nil + } + fullArgs = makeFullArgs(table, opDeleteRule, chain, args...) + out, err = runner.exec.Command(cmdebtables, fullArgs...).CombinedOutput() + if err != nil { + return fmt.Errorf("Failed to delete rule: %v, output: %s", err, out) + } + return nil +} + func (runner *runner) EnsureChain(table Table, chain Chain) (bool, error) { exist := true diff --git a/pkg/util/ebtables/ebtables_test.go b/pkg/util/ebtables/ebtables_test.go index 32ea02572d2..9933493f6ec 100644 --- a/pkg/util/ebtables/ebtables_test.go +++ b/pkg/util/ebtables/ebtables_test.go @@ -124,3 +124,46 @@ Bridge chain: TEST, entries: 0, policy: ACCEPT`), nil, nil t.Errorf("expected error: %q", errStr) } } + +func TestDeleteRule(t *testing.T) { + fcmd := fakeexec.FakeCmd{ + CombinedOutputScript: []fakeexec.FakeAction{ + // Exists + func() ([]byte, []byte, error) { + return []byte(`Bridge table: filter + +Bridge chain: OUTPUT, entries: 4, policy: ACCEPT +-j TEST +`), nil, nil + }, + // Fail to delete + func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 2} }, + // Does not Exists. + func() ([]byte, []byte, error) { + return []byte(`Bridge table: filter + +Bridge chain: TEST, entries: 0, policy: ACCEPT`), nil, nil + }, + }, + } + fexec := fakeexec.FakeExec{ + CommandScript: []fakeexec.FakeCommandAction{ + func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, + }, + } + + runner := New(&fexec) + + err := runner.DeleteRule(TableFilter, ChainOutput, "-j", "TEST") + errStr := "Failed to delete rule: exit 2, output: " + if err == nil || err.Error() != errStr { + t.Errorf("expected error: %q", errStr) + } + + err = runner.DeleteRule(TableFilter, ChainOutput, "-j", "TEST") + if err != nil { + t.Errorf("expected err = nil") + } +}