diff options
Diffstat (limited to 'policy')
-rw-r--r-- | policy/policy.go | 249 | ||||
-rw-r--r-- | policy/policy_test.go | 31 |
2 files changed, 167 insertions, 113 deletions
diff --git a/policy/policy.go b/policy/policy.go index 9bb4bc8c..fe1eb79c 100644 --- a/policy/policy.go +++ b/policy/policy.go @@ -37,7 +37,7 @@ const ( type MaskLengthRangeType int const ( - MASK_LENGTH_RANGE_MIN = iota + MASK_LENGTH_RANGE_MIN MaskLengthRangeType = iota MASK_LENGTH_RANGE_MAX ) @@ -46,42 +46,48 @@ type Policy struct { Statements []Statement } -func NewPolicy(name string, pd config.PolicyDefinition, cdf config.DefinedSets) *Policy { - cst := pd.StatementList +func NewPolicy(name string, pd config.PolicyDefinition, ds config.DefinedSets) *Policy { + stmtList := pd.StatementList st := make([]Statement, 0) p := &Policy{ - Name: name, - Statements: st, + Name: name, } - for _, cs := range cst { - pName := cs.Conditions.MatchPrefixSet - npl := make([]Prefix, 0) - for _, psl := range cdf.PrefixSetList { - if psl.PrefixSetName == pName { - for _, ps := range psl.PrefixList { - npl = append(npl, NewPrefix(ps.Address, ps.Masklength, ps.MasklengthRange)) + 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 { + prefixList = append(prefixList, NewPrefix(pl.Address, pl.Masklength, pl.MasklengthRange)) } } } - nName := cs.Conditions.MatchNeighborSet - nnl := make([]net.IP, 0) - for _, nsl := range cdf.NeighborSetList { - if nsl.NeighborSetName == nName { - for _, nl := range nsl.NeighborInfoList { - nnl = append(nnl, nl.Address) + + 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 := Conditions{ - PrefixList: npl, - NeighborList: nnl, + con := &PrefixConditions{ + PrefixList: prefixList, + NeighborList: neighborList, + MatchSetOptions: statement.Conditions.MatchSetOptions, } - act := Actions{ - AcceptRoute: cs.Actions.AcceptRoute, - RejectRoute: cs.Actions.RejectRoute, + + act := &RoutingActions{ + AcceptRoute: false, } + if statement.Actions.AcceptRoute { + act.AcceptRoute = true + } + s := Statement{ - Name: cs.Name, + Name: statement.Name, Conditions: con, Actions: act, } @@ -97,15 +103,109 @@ type Statement struct { Actions Actions } -type Conditions struct { - //CallPolicy string - PrefixList []Prefix - NeighborList []net.IP +type Conditions interface { + evaluate(table.Path) bool +} + +type DefaultConditions struct { + CallPolicy string +} + +func (c *DefaultConditions) evaluate(path table.Path) bool { + return false +} + +type PrefixConditions struct { + DefaultConditions + PrefixList []Prefix + NeighborList []net.IP + MatchSetOptions config.MatchSetOptionsType +} + +// 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 + } +} + +// 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 { + + if len(c.PrefixList) == 0 { + return true + } + + for _, cp := range c.PrefixList { + if IpPrefixCalculate(path, cp) { + return true + } + } + return false +} + +// 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 { + + if len(c.NeighborList) == 0 { + return true + } + + for _, neighbor := range c.NeighborList { + cAddr := neighbor + pAddr := path.GetSource().Address + if pAddr.Equal(cAddr) { + return true + } + } + return false +} + +type Actions interface { + apply(table.Path) table.Path +} + +type DefaultActions struct { +} + +func (a *DefaultActions) apply(path table.Path) table.Path { + return path } -type Actions struct { +type RoutingActions struct { + DefaultActions AcceptRoute bool - RejectRoute bool +} + +func (r *RoutingActions) apply(path table.Path) table.Path { + if r.AcceptRoute { + return path + } else { + return nil + } +} + +type ModificationActions struct { + DefaultActions + AttrType bgp.BGPAttrType + Value string } type Prefix struct { @@ -121,13 +221,16 @@ func NewPrefix(addr net.IP, maskLen uint8, maskRange string) Prefix { Masklength: maskLen, MasklengthRange: make(map[MaskLengthRangeType]uint8), } + + // TODO: validate mask length by using regexp + idx := strings.Index(maskRange, "..") if idx == -1 { log.WithFields(log.Fields{ "Topic": "Policy", "Address": addr, "Masklength": maskLen, - }).Warn("mask length range of condition is invalid format") + }).Warn("mask length range of condition is invalid format. mask length is not defined.") return p } if idx != 0 { @@ -160,51 +263,20 @@ func NewPrefix(addr net.IP, maskLen uint8, maskRange string) Prefix { //and, subsequent comparison skip if that matches the conditions. func (p *Policy) Apply(path table.Path) (bool, RouteType, table.Path) { for _, statement := range p.Statements { - matchPrefix := false - matchNeighbor := false - if len(statement.Conditions.PrefixList) <= 0 && len(statement.Conditions.NeighborList) <= 0 { - return false, ROUTE_TYPE_NONE, nil - } else if len(statement.Conditions.PrefixList) <= 0 && len(statement.Conditions.NeighborList) > 0 { - matchPrefix = true - matchNeighbor = statement.compareNeighbor(path) - } else if len(statement.Conditions.NeighborList) <= 0 && len(statement.Conditions.PrefixList) > 0 { - matchPrefix = statement.comparePrefix(path) - matchNeighbor = true - } else { - matchPrefix = statement.comparePrefix(path) - matchNeighbor = statement.compareNeighbor(path) - } - an := statement.Actions - - //if match the one of the prefix list and match to any of tye neighbor list, - //determines that matches the conditions of the statement - if matchPrefix && matchNeighbor { - if an.AcceptRoute { - // accept the path - // and return the path updated in acction definition - // TODO update path using acction definition. - // implementation waiting for yang. - newPath := path - log.WithFields(log.Fields{ - "Topic": "Policy", - "Type": "ROUTE_ACCEPT", - "OldPath": path, - "NewPath": newPath, - }).Debug("Apply policy to path") - return true, ROUTE_TYPE_ACCEPT, newPath + result := statement.Conditions.evaluate(path) + log.WithFields(log.Fields{ + "Topic": "Policy", + "Path": path, + "PolicyName": p.Name, + }).Debug("statement.Conditions.evaluate : ", result) + + var p table.Path + if result { + p = statement.Actions.apply(path) + if p != nil { + return true, ROUTE_TYPE_ACCEPT, p } else { - // reject the path - // and return the path updated in acction definition - // TODO update path using acction definition. - // implementation waiting for yang. - newPath := path - log.WithFields(log.Fields{ - "Topic": "Policy", - "Type": "ROUTE_REJECT", - "OldPath": path, - "NewPath": newPath, - }).Debug("Apply policy to path") return true, ROUTE_TYPE_REJECT, nil } } @@ -212,32 +284,7 @@ func (p *Policy) Apply(path table.Path) (bool, RouteType, table.Path) { return false, ROUTE_TYPE_NONE, nil } -//compare prefix of condition policy and nlri of path -//and, subsequent comparison skip if that matches the conditions. -func (s *Statement) comparePrefix(path table.Path) bool { - for _, cp := range s.Conditions.PrefixList { - if IpPrefixCalcurate(path, cp) { - return true - } - } - return false -} - -//compare neighbor ipaddress of condition policy and source of path -//and, subsequent comparison skip if that matches the conditions. -func (s *Statement) compareNeighbor(path table.Path) bool { - for _, neighbor := range s.Conditions.NeighborList { - cAddr := neighbor - pAddr := path.GetSource().Address - if pAddr.Equal(cAddr) { - return true - } - - } - return false -} - -func IpPrefixCalcurate(path table.Path, cPrefix Prefix) bool { +func IpPrefixCalculate(path table.Path, cPrefix Prefix) bool { pAddr := path.GetNlri().(*bgp.NLRInfo).IPAddrPrefix.Prefix pMaskLen := path.GetNlri().(*bgp.NLRInfo).IPAddrPrefix.Length cp := fmt.Sprintf("%s/%d", cPrefix.Address, cPrefix.Masklength) diff --git a/policy/policy_test.go b/policy/policy_test.go index 34c6c5ef..212371b8 100644 --- a/policy/policy_test.go +++ b/policy/policy_test.go @@ -16,6 +16,7 @@ package policy import ( + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet" "github.com/osrg/gobgp/table" @@ -25,6 +26,7 @@ import ( ) func TestPrefixCalcurateNoRange(t *testing.T) { + log.SetLevel(log.DebugLevel) // creatae path peer := &table.PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} origin := bgp.NewPathAttributeOrigin(0) @@ -40,13 +42,13 @@ func TestPrefixCalcurateNoRange(t *testing.T) { path := msg.ToPathList()[0] // test pl1 := NewPrefix(net.ParseIP("10.10.0.0"), 24, "") - match1 := IpPrefixCalcurate(path, pl1) + match1 := IpPrefixCalculate(path, pl1) assert.Equal(t, match1, false) pl2 := NewPrefix(net.ParseIP("10.10.0.101"), 24, "") - match2 := IpPrefixCalcurate(path, pl2) + match2 := IpPrefixCalculate(path, pl2) assert.Equal(t, match2, true) pl3 := NewPrefix(net.ParseIP("10.10.0.0"), 16, "21..24") - match3 := IpPrefixCalcurate(path, pl3) + match3 := IpPrefixCalculate(path, pl3) assert.Equal(t, match3, true) } @@ -66,10 +68,10 @@ func TestPrefixCalcurateInAddress(t *testing.T) { path := msg.ToPathList()[0] // test pl1 := NewPrefix(net.ParseIP("10.11.0.0"), 16, "21..24") - match1 := IpPrefixCalcurate(path, pl1) + match1 := IpPrefixCalculate(path, pl1) assert.Equal(t, match1, false) pl2 := NewPrefix(net.ParseIP("10.10.0.0"), 16, "21..24") - match2 := IpPrefixCalcurate(path, pl2) + match2 := IpPrefixCalculate(path, pl2) assert.Equal(t, match2, true) } @@ -89,10 +91,10 @@ func TestPrefixCalcurateInLength(t *testing.T) { path := msg.ToPathList()[0] // test pl1 := NewPrefix(net.ParseIP("10.10.64.0"), 24, "21..24") - match1 := IpPrefixCalcurate(path, pl1) + match1 := IpPrefixCalculate(path, pl1) assert.Equal(t, match1, false) pl2 := NewPrefix(net.ParseIP("10.10.64.0"), 16, "21..24") - match2 := IpPrefixCalcurate(path, pl2) + match2 := IpPrefixCalculate(path, pl2) assert.Equal(t, match2, true) } @@ -112,13 +114,13 @@ func TestPrefixCalcurateInLengthRange(t *testing.T) { path := msg.ToPathList()[0] // test pl1 := NewPrefix(net.ParseIP("10.10.0.0"), 16, "21..23") - match1 := IpPrefixCalcurate(path, pl1) + match1 := IpPrefixCalculate(path, pl1) assert.Equal(t, match1, false) pl2 := NewPrefix(net.ParseIP("10.10.0.0"), 16, "25..26") - match2 := IpPrefixCalcurate(path, pl2) + match2 := IpPrefixCalculate(path, pl2) assert.Equal(t, match2, false) pl3 := NewPrefix(net.ParseIP("10.10.0.0"), 16, "21..24") - match3 := IpPrefixCalcurate(path, pl3) + match3 := IpPrefixCalculate(path, pl3) assert.Equal(t, match3, true) } @@ -162,6 +164,7 @@ func TestPolicyNotMatchL(t *testing.T) { Conditions: config.Conditions{ MatchPrefixSet: "ps1", MatchNeighborSet: "ns1", + MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL, }, Actions: config.Actions{ AcceptRoute: false, @@ -220,6 +223,7 @@ func TestPolicyMatchAndReject(t *testing.T) { Conditions: config.Conditions{ MatchPrefixSet: "ps1", MatchNeighborSet: "ns1", + MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL, }, Actions: config.Actions{ AcceptRoute: false, @@ -278,6 +282,7 @@ func TestPolicyMatchAndAccept(t *testing.T) { Conditions: config.Conditions{ MatchPrefixSet: "ps1", MatchNeighborSet: "ns1", + MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL, }, Actions: config.Actions{ AcceptRoute: true, @@ -318,7 +323,7 @@ func TestPolicyRejectOnlyPrefixList(t *testing.T) { nexthop = bgp.NewPathAttributeNextHop("10.0.2.2") med = bgp.NewPathAttributeMultiExitDisc(0) pathAttributes = []bgp.PathAttributeInterface{origin, aspath, nexthop, med} - nlri = []bgp.NLRInfo{*bgp.NewNLRInfo(24, "10.10.2.102")} + nlri = []bgp.NLRInfo{*bgp.NewNLRInfo(24, "10.9.2.102")} withdrawnRoutes = []bgp.WithdrawnRoute{} updateMsg = bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri) msg = table.NewProcessMessage(updateMsg, peer) @@ -330,7 +335,7 @@ func TestPolicyRejectOnlyPrefixList(t *testing.T) { PrefixList: []config.Prefix{ config.Prefix{ Address: net.ParseIP("10.10.1.0"), - Masklength: 24, + Masklength: 16, MasklengthRange: "21..24", }}, } @@ -343,6 +348,7 @@ func TestPolicyRejectOnlyPrefixList(t *testing.T) { Conditions: config.Conditions{ MatchPrefixSet: "ps1", MatchNeighborSet: "ns1", + MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL, }, Actions: config.Actions{ AcceptRoute: false, @@ -411,6 +417,7 @@ func TestPolicyRejectOnlyNeighborList(t *testing.T) { Conditions: config.Conditions{ MatchPrefixSet: "ps1", MatchNeighborSet: "ns1", + MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL, }, Actions: config.Actions{ AcceptRoute: false, |