diff options
author | Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp> | 2015-04-28 10:48:46 +0900 |
---|---|---|
committer | Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp> | 2015-04-30 15:52:05 +0900 |
commit | f9577fe75336776c6113ae065062a2455193c798 (patch) | |
tree | f2eb1e636d9bc7c65313683c2e3e944f214b1b03 | |
parent | 4e376c8ca5885910b48282fd10b500b5cba6637b (diff) |
policy: refactor match condition codes
-rw-r--r-- | policy/policy.go | 204 | ||||
-rw-r--r-- | policy/policy_test.go | 94 |
2 files changed, 182 insertions, 116 deletions
diff --git a/policy/policy.go b/policy/policy.go index 9dc3632e..5a683e36 100644 --- a/policy/policy.go +++ b/policy/policy.go @@ -43,62 +43,45 @@ const ( type Policy struct { Name string - Statements []Statement + Statements []*Statement } func NewPolicy(name string, pd config.PolicyDefinition, ds config.DefinedSets) *Policy { stmtList := pd.StatementList - st := make([]Statement, 0) + st := make([]*Statement, 0) p := &Policy{ Name: name, } + for _, statement := range stmtList { - prefixSetName := statement.Conditions.MatchPrefixSet - prefixList := make([]Prefix, 0) - for _, ps := range ds.PrefixSetList { - if ps.PrefixSetName == prefixSetName { - for _, pl := range ps.PrefixList { - prefix, e := NewPrefix(pl.Address, pl.Masklength, pl.MasklengthRange) - if e != nil { - log.WithFields(log.Fields{ - "Topic": "Policy", - "prefix": prefix, - "msg": e, - }).Warn("failed to generate a NewPrefix from configration.") - } - prefixList = append(prefixList, prefix) - } - } - } + conditions := make([]Condition,0) + + // prefix match + prefixSetName := statement.Conditions.MatchPrefixSet + pc := NewPrefixCondition(prefixSetName, ds.PrefixSetList) + conditions = append(conditions, pc) + // neighbor match neighborSetName := statement.Conditions.MatchNeighborSet - neighborList := make([]net.IP, 0) - for _, neighborSet := range ds.NeighborSetList { - if neighborSet.NeighborSetName == neighborSetName { - for _, nl := range neighborSet.NeighborInfoList { - neighborList = append(neighborList, nl.Address) - } - } - } - con := &PrefixConditions{ - PrefixList: prefixList, - NeighborList: neighborList, - MatchSetOptions: statement.Conditions.MatchSetOptions, - } + nc := NewNeighborCondition(neighborSetName, ds.NeighborSetList) + conditions = append(conditions, nc) - act := &RoutingActions{ + action := &RoutingActions{ AcceptRoute: false, } + if statement.Actions.AcceptRoute { - act.AcceptRoute = true + action.AcceptRoute = true } - s := Statement{ + s := &Statement{ Name: statement.Name, - Conditions: con, - Actions: act, + Conditions: conditions, + Actions: action, + MatchSetOptions: statement.Conditions.MatchSetOptions, } + st = append(st, s) } p.Statements = st @@ -106,56 +89,109 @@ func NewPolicy(name string, pd config.PolicyDefinition, ds config.DefinedSets) * } type Statement struct { - Name string - Conditions Conditions - Actions Actions + Name string + Conditions []Condition + Actions Actions + MatchSetOptions config.MatchSetOptionsType +} + +// evaluate each condition in the statement according to MatchSetOptions +func (s *Statement) evaluate(p table.Path) bool { + + optionType := s.MatchSetOptions + + result := false + if optionType == config.MATCH_SET_OPTIONS_TYPE_ALL { + result = true + } + + for _, condition := range s.Conditions { + + r := condition.evaluate(p) + + switch optionType { + case config.MATCH_SET_OPTIONS_TYPE_ALL: + result = result && r + if !result { + return false + } + + case config.MATCH_SET_OPTIONS_TYPE_ANY: + result = result || r + if result { + return true + } + + case config.MATCH_SET_OPTIONS_TYPE_INVERT: + result = result || r + if result { + return false + } + + default: + return false + } + } + + if optionType == config.MATCH_SET_OPTIONS_TYPE_INVERT { + return !result + } else { + return result + } } -type Conditions interface { +type Condition interface { evaluate(table.Path) bool } -type DefaultConditions struct { +type DefaultCondition struct { CallPolicy string } -func (c *DefaultConditions) evaluate(path table.Path) bool { +func (c *DefaultCondition) evaluate(path table.Path) bool { return false } -type PrefixConditions struct { - DefaultConditions - PrefixList []Prefix - NeighborList []net.IP - MatchSetOptions config.MatchSetOptionsType +type PrefixCondition struct { + DefaultCondition + PrefixList []Prefix } -// evaluate path's prefix and neighbor's address with conditions -// return value depends on MatchSetOptions -func (c *PrefixConditions) evaluate(path table.Path) bool { - pref := c.evaluatePrefix(path) - log.Debug("evaluate prefix : ", pref) - neigh := c.evaluateNeighbor(path) - log.Debug("evaluate neighbor : ", neigh) - - switch c.MatchSetOptions { - case config.MATCH_SET_OPTIONS_TYPE_ALL: - return pref && neigh - case config.MATCH_SET_OPTIONS_TYPE_ANY: - return pref || neigh - case config.MATCH_SET_OPTIONS_TYPE_INVERT: - return !(pref || neigh) - default: - return false +func NewPrefixCondition(prefixSetName string, defPrefixList []config.PrefixSet) *PrefixCondition { + + prefixList := make([]Prefix, 0) + for _, ps := range defPrefixList { + if ps.PrefixSetName == prefixSetName { + for _, pl := range ps.PrefixList { + prefix, e := NewPrefix(pl.Address, pl.Masklength, pl.MasklengthRange) + if e != nil { + log.WithFields(log.Fields{ + "Topic": "Policy", + "prefix": prefix, + "msg": e, + }).Warn("failed to generate a NewPrefix from configration.") + } else { + prefixList = append(prefixList, prefix) + } + } + } + } + + pc := &PrefixCondition{ + PrefixList: prefixList, } + + return pc + } // compare prefixes in this condition and nlri of path and // subsequent comparison is skipped if that matches the conditions. // If PrefixList's length is zero, return true. -func (c *PrefixConditions) evaluatePrefix(path table.Path) bool { +func (c *PrefixCondition) evaluate(path table.Path) bool { if len(c.PrefixList) == 0 { + log.Debug("PrefixList doesn't have elements") return true } @@ -168,12 +204,36 @@ func (c *PrefixConditions) evaluatePrefix(path table.Path) bool { return false } +type NeighborCondition struct { + DefaultCondition + NeighborList []net.IP +} + +func NewNeighborCondition(neighborSetName string, defNeighborSetList []config.NeighborSet) *NeighborCondition { + + neighborList := make([]net.IP, 0) + for _, neighborSet := range defNeighborSetList { + if neighborSet.NeighborSetName == neighborSetName { + for _, nl := range neighborSet.NeighborInfoList { + neighborList = append(neighborList, nl.Address) + } + } + } + + nc := &NeighborCondition{ + NeighborList: neighborList, + } + + return nc +} + // compare neighbor ipaddress of this condition and source address of path // and, subsequent comparisons are skipped if that matches the conditions. // If NeighborList's length is zero, return true. -func (c *PrefixConditions) evaluateNeighbor(path table.Path) bool { +func (c *NeighborCondition) evaluate(path table.Path) bool { if len(c.NeighborList) == 0 { + log.Debug("NeighborList doesn't have elements") return true } @@ -244,8 +304,14 @@ func NewPrefix(addr net.IP, maskLen uint8, maskRange string) (Prefix, error) { idx := strings.Index(maskRange, "..") if idx == -1 { - return p, fmt.Errorf("mask length range of condition is invalid format. mask length is not defined.") + log.WithFields(log.Fields{ + "Topic": "Policy", + "Type": "Prefix", + "MaskRangeFormat": maskRange, + }).Warn("mask length range format is invalid. mask range was skipped.") + return p, nil } + if idx != 0 { min, e := strconv.ParseUint(maskRange[:idx], 10, 8) if e != nil { @@ -269,7 +335,7 @@ func NewPrefix(addr net.IP, maskLen uint8, maskRange string) (Prefix, error) { func (p *Policy) Apply(path table.Path) (bool, RouteType, table.Path) { for _, statement := range p.Statements { - result := statement.Conditions.evaluate(path) + result := statement.evaluate(path) log.WithFields(log.Fields{ "Topic": "Policy", "Path": path, diff --git a/policy/policy_test.go b/policy/policy_test.go index ac2c930b..335f1a66 100644 --- a/policy/policy_test.go +++ b/policy/policy_test.go @@ -42,13 +42,13 @@ func TestPrefixCalcurateNoRange(t *testing.T) { // test pl1, _ := NewPrefix(net.ParseIP("10.10.0.0"), 24, "") match1 := IpPrefixCalculate(path, pl1) - assert.Equal(t, match1, false) + assert.Equal(t, false, match1) pl2, _ := NewPrefix(net.ParseIP("10.10.0.101"), 24, "") match2 := IpPrefixCalculate(path, pl2) - assert.Equal(t, match2, true) + assert.Equal(t, true, match2) pl3, _ := NewPrefix(net.ParseIP("10.10.0.0"), 16, "21..24") match3 := IpPrefixCalculate(path, pl3) - assert.Equal(t, match3, true) + assert.Equal(t, true, match3) } func TestPrefixCalcurateAddress(t *testing.T) { @@ -67,10 +67,10 @@ func TestPrefixCalcurateAddress(t *testing.T) { // test pl1, _ := NewPrefix(net.ParseIP("10.11.0.0"), 16, "21..24") match1 := IpPrefixCalculate(path, pl1) - assert.Equal(t, match1, false) + assert.Equal(t, false, match1) pl2, _ := NewPrefix(net.ParseIP("10.10.0.0"), 16, "21..24") match2 := IpPrefixCalculate(path, pl2) - assert.Equal(t, match2, true) + assert.Equal(t, true, match2) } func TestPrefixCalcurateLength(t *testing.T) { @@ -89,10 +89,10 @@ func TestPrefixCalcurateLength(t *testing.T) { // test pl1, _ := NewPrefix(net.ParseIP("10.10.64.0"), 24, "21..24") match1 := IpPrefixCalculate(path, pl1) - assert.Equal(t, match1, false) + assert.Equal(t, false, match1) pl2, _ := NewPrefix(net.ParseIP("10.10.64.0"), 16, "21..24") match2 := IpPrefixCalculate(path, pl2) - assert.Equal(t, match2, true) + assert.Equal(t, true, match2) } func TestPrefixCalcurateLengthRange(t *testing.T) { @@ -111,13 +111,13 @@ func TestPrefixCalcurateLengthRange(t *testing.T) { // test pl1, _ := NewPrefix(net.ParseIP("10.10.0.0"), 16, "21..23") match1 := IpPrefixCalculate(path, pl1) - assert.Equal(t, match1, false) + assert.Equal(t, false, match1) pl2, _ := NewPrefix(net.ParseIP("10.10.0.0"), 16, "25..26") match2 := IpPrefixCalculate(path, pl2) - assert.Equal(t, match2, false) + assert.Equal(t, false, match2) pl3, _ := NewPrefix(net.ParseIP("10.10.0.0"), 16, "21..24") match3 := IpPrefixCalculate(path, pl3) - assert.Equal(t, match3, true) + assert.Equal(t, true, match3) } func TestPrefixCalcurateNoRangeIPv6(t *testing.T) { @@ -138,13 +138,13 @@ func TestPrefixCalcurateNoRangeIPv6(t *testing.T) { // test pl1, _ := NewPrefix(net.ParseIP("2001:123:123::"), 48, "") match1 := IpPrefixCalculate(path, pl1) - assert.Equal(t, match1, false) + assert.Equal(t, false, match1) pl2, _ := NewPrefix(net.ParseIP("2001:123:123:1::"), 64, "") match2 := IpPrefixCalculate(path, pl2) - assert.Equal(t, match2, true) + assert.Equal(t, true, match2) pl3, _ := NewPrefix(net.ParseIP("2001:123:123::"), 48, "64..80") match3 := IpPrefixCalculate(path, pl3) - assert.Equal(t, match3, true) + assert.Equal(t, true, match3) } func TestPrefixCalcurateAddressIPv6(t *testing.T) { @@ -164,10 +164,10 @@ func TestPrefixCalcurateAddressIPv6(t *testing.T) { // test pl1, _ := NewPrefix(net.ParseIP("2001:123:128::"), 48, "64..80") match1 := IpPrefixCalculate(path, pl1) - assert.Equal(t, match1, false) + assert.Equal(t, false, match1) pl2, _ := NewPrefix(net.ParseIP("2001:123:123::"), 48, "64..80") match2 := IpPrefixCalculate(path, pl2) - assert.Equal(t, match2, true) + assert.Equal(t, true, match2) } func TestPrefixCalcurateLengthIPv6(t *testing.T) { @@ -187,10 +187,10 @@ func TestPrefixCalcurateLengthIPv6(t *testing.T) { // test pl1, _ := NewPrefix(net.ParseIP("2001:123:123:64::"), 64, "64..80") match1 := IpPrefixCalculate(path, pl1) - assert.Equal(t, match1, false) + assert.Equal(t, false, match1) pl2, _ := NewPrefix(net.ParseIP("2001:123:123:64::"), 48, "64..80") match2 := IpPrefixCalculate(path, pl2) - assert.Equal(t, match2, true) + assert.Equal(t, true, match2) } func TestPrefixCalcurateLengthRangeIPv6(t *testing.T) { @@ -210,13 +210,13 @@ func TestPrefixCalcurateLengthRangeIPv6(t *testing.T) { // test pl1, _ := NewPrefix(net.ParseIP("2001:123:123::"), 48, "62..63") match1 := IpPrefixCalculate(path, pl1) - assert.Equal(t, match1, false) + assert.Equal(t, false, match1) pl2, _ := NewPrefix(net.ParseIP("2001:123:123::"), 48, "65..66") match2 := IpPrefixCalculate(path, pl2) - assert.Equal(t, match2, false) + assert.Equal(t, false, match2) pl3, _ := NewPrefix(net.ParseIP("2001:123:123::"), 48, "63..65") match3 := IpPrefixCalculate(path, pl3) - assert.Equal(t, match3, true) + assert.Equal(t, true, match3) } func TestPolicyNotMatch(t *testing.T) { @@ -272,9 +272,9 @@ func TestPolicyNotMatch(t *testing.T) { df := pl.DefinedSets p := NewPolicy(pName, pl.PolicyDefinitionList[0], df) match, pType, newPath := p.Apply(path) - assert.Equal(t, match, false) - assert.Equal(t, pType, ROUTE_TYPE_NONE) - assert.Equal(t, newPath, nil) + assert.Equal(t, false, match) + assert.Equal(t, ROUTE_TYPE_NONE, pType) + assert.Equal(t, nil, newPath) } func TestPolicyMatchAndReject(t *testing.T) { @@ -330,9 +330,9 @@ func TestPolicyMatchAndReject(t *testing.T) { df := pl.DefinedSets p := NewPolicy(pName, pl.PolicyDefinitionList[0], df) match, pType, newPath := p.Apply(path) - assert.Equal(t, match, true) - assert.Equal(t, pType, ROUTE_TYPE_REJECT) - assert.Equal(t, newPath, nil) + assert.Equal(t, true, match) + assert.Equal(t, ROUTE_TYPE_REJECT, pType) + assert.Equal(t, nil, newPath) } func TestPolicyMatchAndAccept(t *testing.T) { @@ -388,9 +388,9 @@ func TestPolicyMatchAndAccept(t *testing.T) { df := pl.DefinedSets p := NewPolicy(pName, pl.PolicyDefinitionList[0], df) match, pType, newPath := p.Apply(path) - assert.Equal(t, match, true) - assert.Equal(t, pType, ROUTE_TYPE_ACCEPT) - assert.Equal(t, newPath, path) + assert.Equal(t, true, match) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.Equal(t, path, newPath) } func TestPolicyRejectOnlyPrefixSet(t *testing.T) { @@ -452,14 +452,14 @@ func TestPolicyRejectOnlyPrefixSet(t *testing.T) { df := pl.DefinedSets p := NewPolicy(pName, pl.PolicyDefinitionList[0], df) match, pType, newPath := p.Apply(path1) - assert.Equal(t, match, true) - assert.Equal(t, pType, ROUTE_TYPE_REJECT) - assert.Equal(t, newPath, nil) + assert.Equal(t, true, match) + assert.Equal(t, ROUTE_TYPE_REJECT, pType) + assert.Equal(t, nil, newPath) match2, pType2, newPath2 := p.Apply(path2) - assert.Equal(t, match2, false) - assert.Equal(t, pType2, ROUTE_TYPE_NONE) - assert.Equal(t, newPath2, nil) + assert.Equal(t, false, match2) + assert.Equal(t, ROUTE_TYPE_NONE, pType2) + assert.Equal(t, nil, newPath2) } func TestPolicyRejectOnlyNeighborSet(t *testing.T) { @@ -519,14 +519,14 @@ func TestPolicyRejectOnlyNeighborSet(t *testing.T) { df := pl.DefinedSets p := NewPolicy(pName, pl.PolicyDefinitionList[0], df) match, pType, newPath := p.Apply(path1) - assert.Equal(t, match, true) - assert.Equal(t, pType, ROUTE_TYPE_REJECT) - assert.Equal(t, newPath, nil) + assert.Equal(t, true, match) + assert.Equal(t, ROUTE_TYPE_REJECT, pType) + assert.Equal(t, nil, newPath) match2, pType2, newPath2 := p.Apply(path2) - assert.Equal(t, match2, false) - assert.Equal(t, pType2, ROUTE_TYPE_NONE) - assert.Equal(t, newPath2, nil) + assert.Equal(t, false, match2) + assert.Equal(t, ROUTE_TYPE_NONE, pType2) + assert.Equal(t, nil, newPath2) } func TestPolicyDifferentRoutefamilyOfPathAndPolicy(t *testing.T) { @@ -623,12 +623,12 @@ func TestPolicyDifferentRoutefamilyOfPathAndPolicy(t *testing.T) { df := pl.DefinedSets p := NewPolicy(pName, pl.PolicyDefinitionList[0], df) match1, pType1, newPath1 := p.Apply(pathIPv4) - assert.Equal(t, match1, true) - assert.Equal(t, pType1, ROUTE_TYPE_REJECT) - assert.Equal(t, newPath1, nil) + assert.Equal(t, true, match1) + assert.Equal(t, ROUTE_TYPE_REJECT, pType1) + assert.Equal(t, nil, newPath1) match2, pType2, newPath2 := p.Apply(pathIPv6) - assert.Equal(t, match2, true) - assert.Equal(t, pType2, ROUTE_TYPE_REJECT) - assert.Equal(t, newPath2, nil) + assert.Equal(t, true, match2) + assert.Equal(t, ROUTE_TYPE_REJECT, pType2) + assert.Equal(t, nil, newPath2) } |