summaryrefslogtreecommitdiffhomepage
path: root/policy
diff options
context:
space:
mode:
Diffstat (limited to 'policy')
-rw-r--r--policy/policy.go249
-rw-r--r--policy/policy_test.go31
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,