diff --git a/system.go b/system.go index 035d499..5cc6783 100644 --- a/system.go +++ b/system.go @@ -83,6 +83,11 @@ func allRuleLocations(fd int, ifname string) ([]uint32, uint32, error) { return nil, 0, err } + if all.ruleCnt > cnt.ruleCnt { + return nil, 0, fmt.Errorf("%s reported %d filter locations into room for %d", + ifname, all.ruleCnt, cnt.ruleCnt) + } + raw := buf[locOff:] locs := make([]uint32, 0, all.ruleCnt) for i := 0; i < int(all.ruleCnt); i++ { @@ -171,9 +176,16 @@ func checkFlowRules(fd int, ifname string, ethertypes []uint16) checkResult { taken[loc] = true } + // Inserting at a taken location would evict it, and would then leave every + // later ethertype evicting the one before it at that same location. next := capacity - 1 for i, et := range ethertypes { - for taken[next] && next > 0 { + for taken[next] { + if next == 0 { + res.err = fmt.Errorf("no free filter location below %d for ethertype 0x%04x", + capacity, et) + return res + } next-- } if err := insertEtherRule(fd, ifname, et, uint64(i), next); err != nil { @@ -586,8 +598,7 @@ func withIoctlSocket(fn func(fd int) []checkResult) []checkResult { } // Nothing here waits for a carrier: the two ports are the two ends of the cable -// under test, so with no cable there will never be one, and a dead wire is a -// result to report rather than a reason to refuse to start. +// under test, so with no cable there is never going to be one. func configureSystem(ifnames []string, ethertypes []uint16) []checkResult { return withIoctlSocket(func(fd int) []checkResult { out := []checkResult{checkGovernor(wantGovernor)}