summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorHiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp>2015-04-28 20:13:10 +0900
committerHiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp>2015-04-30 15:52:05 +0900
commit483d37a1b4b5ea053ec7c95073b9f05a2152385f (patch)
tree24c92c8779db8073a31a533b63a77fd4930d6c5c
parentf9577fe75336776c6113ae065062a2455193c798 (diff)
policy: add AsPathLength match
-rw-r--r--policy/policy.go91
-rw-r--r--policy/policy_test.go170
-rw-r--r--table/path.go29
3 files changed, 261 insertions, 29 deletions
diff --git a/policy/policy.go b/policy/policy.go
index 5a683e36..10ab0736 100644
--- a/policy/policy.go
+++ b/policy/policy.go
@@ -41,6 +41,17 @@ const (
MASK_LENGTH_RANGE_MAX
)
+type AttributeComparison int
+
+const (
+ // "== comparison"
+ ATTRIBUTE_EQ AttributeComparison = iota
+ // ">= comparison"
+ ATTRIBUTE_GE
+ // "<= comparison"
+ ATTRIBUTE_LE
+)
+
type Policy struct {
Name string
Statements []*Statement
@@ -55,7 +66,7 @@ func NewPolicy(name string, pd config.PolicyDefinition, ds config.DefinedSets) *
for _, statement := range stmtList {
- conditions := make([]Condition,0)
+ conditions := make([]Condition, 0)
// prefix match
prefixSetName := statement.Conditions.MatchPrefixSet
@@ -67,6 +78,13 @@ func NewPolicy(name string, pd config.PolicyDefinition, ds config.DefinedSets) *
nc := NewNeighborCondition(neighborSetName, ds.NeighborSetList)
conditions = append(conditions, nc)
+ // AsPathLengthCondition
+ c := statement.Conditions.BgpConditions.AsPathLength
+ ac := NewAsPathLengthCondition(c)
+ if ac != nil {
+ conditions = append(conditions, ac)
+ }
+
action := &RoutingActions{
AcceptRoute: false,
}
@@ -76,9 +94,9 @@ func NewPolicy(name string, pd config.PolicyDefinition, ds config.DefinedSets) *
}
s := &Statement{
- Name: statement.Name,
- Conditions: conditions,
- Actions: action,
+ Name: statement.Name,
+ Conditions: conditions,
+ Actions: action,
MatchSetOptions: statement.Conditions.MatchSetOptions,
}
@@ -169,7 +187,7 @@ func NewPrefixCondition(prefixSetName string, defPrefixList []config.PrefixSet)
"Topic": "Policy",
"prefix": prefix,
"msg": e,
- }).Warn("failed to generate a NewPrefix from configration.")
+ }).Error("failed to generate a NewPrefix from configration.")
} else {
prefixList = append(prefixList, prefix)
}
@@ -196,7 +214,7 @@ func (c *PrefixCondition) evaluate(path table.Path) bool {
}
for _, cp := range c.PrefixList {
- if IpPrefixCalculate(path, cp) {
+ if ipPrefixCalculate(path, cp) {
log.Debug("prefix matched : ", cp)
return true
}
@@ -247,6 +265,60 @@ func (c *NeighborCondition) evaluate(path table.Path) bool {
return false
}
+type AsPathLengthCondition struct {
+ DefaultCondition
+ Value uint32
+ Operator AttributeComparison
+}
+
+// create AsPathLengthCondition object
+func NewAsPathLengthCondition(defAsPathLength config.AsPathLength) *AsPathLengthCondition {
+
+ value := defAsPathLength.Value
+ var op AttributeComparison
+
+ switch defAsPathLength.Operator {
+ case "eq":
+ op = ATTRIBUTE_EQ
+
+ case "ge":
+ op = ATTRIBUTE_GE
+
+ case "le":
+ op = ATTRIBUTE_LE
+ default:
+ return nil
+ }
+
+ ac := &AsPathLengthCondition{
+ Value: value,
+ Operator: op,
+ }
+
+ return ac
+}
+
+// compare AS_PATH length in the message's AS_PATH attribute with
+// the one in condition.
+func (c *AsPathLengthCondition) evaluate(path table.Path) bool {
+
+ length := uint32(path.GetAsPathLen())
+
+ switch c.Operator {
+ case ATTRIBUTE_EQ:
+ return c.Value == length
+
+ case ATTRIBUTE_GE:
+ return c.Value <= length
+
+ case ATTRIBUTE_LE:
+ return c.Value >= length
+ default:
+ return false
+ }
+
+}
+
type Actions interface {
apply(table.Path) table.Path
}
@@ -330,8 +402,9 @@ func NewPrefix(addr net.IP, maskLen uint8, maskRange string) (Prefix, error) {
return p, nil
}
-//compare path and condition of policy
-//and, subsequent comparison skip if that matches the conditions.
+// Compare path with a policy's condition in stored order in the policy.
+// If a condition match, then this function stops evaluation and
+// subsequent conditions are skipped.
func (p *Policy) Apply(path table.Path) (bool, RouteType, table.Path) {
for _, statement := range p.Statements {
@@ -355,7 +428,7 @@ func (p *Policy) Apply(path table.Path) (bool, RouteType, table.Path) {
return false, ROUTE_TYPE_NONE, nil
}
-func IpPrefixCalculate(path table.Path, cPrefix Prefix) bool {
+func ipPrefixCalculate(path table.Path, cPrefix Prefix) bool {
rf := path.GetRouteFamily()
log.Debug("path routefamily : ", rf.String())
var pAddr net.IP
diff --git a/policy/policy_test.go b/policy/policy_test.go
index 335f1a66..1f27fd4c 100644
--- a/policy/policy_test.go
+++ b/policy/policy_test.go
@@ -41,13 +41,13 @@ func TestPrefixCalcurateNoRange(t *testing.T) {
path := table.ProcessMessage(updateMsg, peer)[0]
// test
pl1, _ := NewPrefix(net.ParseIP("10.10.0.0"), 24, "")
- match1 := IpPrefixCalculate(path, pl1)
+ match1 := ipPrefixCalculate(path, pl1)
assert.Equal(t, false, match1)
pl2, _ := NewPrefix(net.ParseIP("10.10.0.101"), 24, "")
- match2 := IpPrefixCalculate(path, pl2)
+ match2 := ipPrefixCalculate(path, pl2)
assert.Equal(t, true, match2)
pl3, _ := NewPrefix(net.ParseIP("10.10.0.0"), 16, "21..24")
- match3 := IpPrefixCalculate(path, pl3)
+ match3 := ipPrefixCalculate(path, pl3)
assert.Equal(t, true, match3)
}
@@ -66,10 +66,10 @@ func TestPrefixCalcurateAddress(t *testing.T) {
path := table.ProcessMessage(updateMsg, peer)[0]
// test
pl1, _ := NewPrefix(net.ParseIP("10.11.0.0"), 16, "21..24")
- match1 := IpPrefixCalculate(path, pl1)
+ match1 := ipPrefixCalculate(path, pl1)
assert.Equal(t, false, match1)
pl2, _ := NewPrefix(net.ParseIP("10.10.0.0"), 16, "21..24")
- match2 := IpPrefixCalculate(path, pl2)
+ match2 := ipPrefixCalculate(path, pl2)
assert.Equal(t, true, match2)
}
@@ -88,10 +88,10 @@ func TestPrefixCalcurateLength(t *testing.T) {
path := table.ProcessMessage(updateMsg, peer)[0]
// test
pl1, _ := NewPrefix(net.ParseIP("10.10.64.0"), 24, "21..24")
- match1 := IpPrefixCalculate(path, pl1)
+ match1 := ipPrefixCalculate(path, pl1)
assert.Equal(t, false, match1)
pl2, _ := NewPrefix(net.ParseIP("10.10.64.0"), 16, "21..24")
- match2 := IpPrefixCalculate(path, pl2)
+ match2 := ipPrefixCalculate(path, pl2)
assert.Equal(t, true, match2)
}
@@ -110,13 +110,13 @@ func TestPrefixCalcurateLengthRange(t *testing.T) {
path := table.ProcessMessage(updateMsg, peer)[0]
// test
pl1, _ := NewPrefix(net.ParseIP("10.10.0.0"), 16, "21..23")
- match1 := IpPrefixCalculate(path, pl1)
+ match1 := ipPrefixCalculate(path, pl1)
assert.Equal(t, false, match1)
pl2, _ := NewPrefix(net.ParseIP("10.10.0.0"), 16, "25..26")
- match2 := IpPrefixCalculate(path, pl2)
+ match2 := ipPrefixCalculate(path, pl2)
assert.Equal(t, false, match2)
pl3, _ := NewPrefix(net.ParseIP("10.10.0.0"), 16, "21..24")
- match3 := IpPrefixCalculate(path, pl3)
+ match3 := ipPrefixCalculate(path, pl3)
assert.Equal(t, true, match3)
}
@@ -137,13 +137,13 @@ func TestPrefixCalcurateNoRangeIPv6(t *testing.T) {
path := table.ProcessMessage(updateMsg, peer)[0]
// test
pl1, _ := NewPrefix(net.ParseIP("2001:123:123::"), 48, "")
- match1 := IpPrefixCalculate(path, pl1)
+ match1 := ipPrefixCalculate(path, pl1)
assert.Equal(t, false, match1)
pl2, _ := NewPrefix(net.ParseIP("2001:123:123:1::"), 64, "")
- match2 := IpPrefixCalculate(path, pl2)
+ match2 := ipPrefixCalculate(path, pl2)
assert.Equal(t, true, match2)
pl3, _ := NewPrefix(net.ParseIP("2001:123:123::"), 48, "64..80")
- match3 := IpPrefixCalculate(path, pl3)
+ match3 := ipPrefixCalculate(path, pl3)
assert.Equal(t, true, match3)
}
@@ -163,10 +163,10 @@ func TestPrefixCalcurateAddressIPv6(t *testing.T) {
path := table.ProcessMessage(updateMsg, peer)[0]
// test
pl1, _ := NewPrefix(net.ParseIP("2001:123:128::"), 48, "64..80")
- match1 := IpPrefixCalculate(path, pl1)
+ match1 := ipPrefixCalculate(path, pl1)
assert.Equal(t, false, match1)
pl2, _ := NewPrefix(net.ParseIP("2001:123:123::"), 48, "64..80")
- match2 := IpPrefixCalculate(path, pl2)
+ match2 := ipPrefixCalculate(path, pl2)
assert.Equal(t, true, match2)
}
@@ -186,10 +186,10 @@ func TestPrefixCalcurateLengthIPv6(t *testing.T) {
path := table.ProcessMessage(updateMsg, peer)[0]
// test
pl1, _ := NewPrefix(net.ParseIP("2001:123:123:64::"), 64, "64..80")
- match1 := IpPrefixCalculate(path, pl1)
+ match1 := ipPrefixCalculate(path, pl1)
assert.Equal(t, false, match1)
pl2, _ := NewPrefix(net.ParseIP("2001:123:123:64::"), 48, "64..80")
- match2 := IpPrefixCalculate(path, pl2)
+ match2 := ipPrefixCalculate(path, pl2)
assert.Equal(t, true, match2)
}
@@ -209,13 +209,13 @@ func TestPrefixCalcurateLengthRangeIPv6(t *testing.T) {
path := table.ProcessMessage(updateMsg, peer)[0]
// test
pl1, _ := NewPrefix(net.ParseIP("2001:123:123::"), 48, "62..63")
- match1 := IpPrefixCalculate(path, pl1)
+ match1 := ipPrefixCalculate(path, pl1)
assert.Equal(t, false, match1)
pl2, _ := NewPrefix(net.ParseIP("2001:123:123::"), 48, "65..66")
- match2 := IpPrefixCalculate(path, pl2)
+ match2 := ipPrefixCalculate(path, pl2)
assert.Equal(t, false, match2)
pl3, _ := NewPrefix(net.ParseIP("2001:123:123::"), 48, "63..65")
- match3 := IpPrefixCalculate(path, pl3)
+ match3 := ipPrefixCalculate(path, pl3)
assert.Equal(t, true, match3)
}
@@ -632,3 +632,133 @@ func TestPolicyDifferentRoutefamilyOfPathAndPolicy(t *testing.T) {
assert.Equal(t, ROUTE_TYPE_REJECT, pType2)
assert.Equal(t, nil, newPath2)
}
+
+func TestAsPathLengthConditionEvaluate(t *testing.T) {
+ // setup
+ // create path
+ peer := &table.PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
+ origin := bgp.NewPathAttributeOrigin(0)
+ aspathParam := []bgp.AsPathParamInterface{
+ bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 65005}),
+ bgp.NewAsPathParam(1, []uint16{65001, 65000, 65004, 65005}),
+ }
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(0)
+ pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
+ nlri := []bgp.NLRInfo{*bgp.NewNLRInfo(24, "10.10.0.101")}
+ withdrawnRoutes := []bgp.WithdrawnRoute{}
+ updateMsg := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
+ table.UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
+ msg := table.NewProcessMessage(updateMsg, peer)
+ path := msg.ToPathList()[0]
+
+ // create match condition
+ asPathLength := config.AsPathLength{
+ Operator: "eq",
+ Value: 8,
+ }
+ c := NewAsPathLengthCondition(asPathLength)
+
+ // test
+ assert.Equal(t, true, c.evaluate(path))
+
+ // create match condition
+ asPathLength = config.AsPathLength{
+ Operator: "ge",
+ Value: 3,
+ }
+ c = NewAsPathLengthCondition(asPathLength)
+
+ // test
+ assert.Equal(t, true, c.evaluate(path))
+
+ // create match condition
+ asPathLength = config.AsPathLength{
+ Operator: "le",
+ Value: 3,
+ }
+ c = NewAsPathLengthCondition(asPathLength)
+
+ // test
+ assert.Equal(t, false, c.evaluate(path))
+}
+
+func TestAsPathLengthConditionWithOtherCondition(t *testing.T) {
+ // setup
+ // create path
+ peer := &table.PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
+ origin := bgp.NewPathAttributeOrigin(0)
+ aspathParam := []bgp.AsPathParamInterface{
+ bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 65004, 65005}),
+ bgp.NewAsPathParam(1, []uint16{65001, 65000, 65004, 65005}),
+ }
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(0)
+ pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
+ nlri := []bgp.NLRInfo{*bgp.NewNLRInfo(24, "10.10.0.101")}
+ withdrawnRoutes := []bgp.WithdrawnRoute{}
+ updateMsg := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
+ table.UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
+ msg := table.NewProcessMessage(updateMsg, peer)
+ path := msg.ToPathList()[0]
+
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.1.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.1.1"),
+ }},
+ }
+
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ // create match condition
+ asPathLength := config.AsPathLength{
+ Operator: "le",
+ Value: 10,
+ }
+
+ bgpCondition := config.BgpConditions{
+ AsPathLength: asPathLength,
+ }
+
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY,
+ BgpConditions: bgpCondition,
+ },
+ Actions: config.Actions{
+ RejectRoute: true,
+ },
+ }
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+
+ //test
+ pName := "pd1"
+ df := pl.DefinedSets
+ p := NewPolicy(pName, pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_REJECT, pType)
+ assert.Equal(t, nil, newPath)
+
+}
diff --git a/table/path.go b/table/path.go
index 29d8a92d..a1f87391 100644
--- a/table/path.go
+++ b/table/path.go
@@ -33,6 +33,7 @@ type Path interface {
getPathAttr(bgp.BGPAttrType) (int, bgp.PathAttributeInterface)
updatePathAttrs(global *config.Global, peer *config.Neighbor)
GetRouteFamily() bgp.RouteFamily
+ GetAsPathLen() int
setSource(source *PeerInfo)
GetSource() *PeerInfo
GetSourceAs() uint32
@@ -332,6 +333,34 @@ func (pi *PathDefault) getPrefix() string {
return pi.nlri.String()
}
+// return total length of AS_PATH whose type is AS_SEQ or AS_SET
+func (pd *PathDefault) GetAsPathLen() int {
+
+ aslen := func(p *bgp.As4PathParam) int {
+ if p.Type == bgp.BGP_ASPATH_ATTR_TYPE_SEQ || p.Type == bgp.BGP_ASPATH_ATTR_TYPE_SET {
+ return p.ASLen()
+ }
+ return 0
+ }
+
+ var length int = 0
+ if _, attr := pd.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH); attr != nil {
+ aspath := attr.(*bgp.PathAttributeAsPath)
+ for _, paramIf := range aspath.Value {
+ segment := paramIf.(*bgp.As4PathParam)
+ length += aslen(segment)
+ }
+
+ } else {
+ _, attr := pd.getPathAttr(bgp.BGP_ATTR_TYPE_AS4_PATH)
+ aspath := attr.(*bgp.PathAttributeAs4Path)
+ for _, segment := range aspath.Value {
+ length += aslen(segment)
+ }
+ }
+ return length
+}
+
// create Path object based on route family
func CreatePath(source *PeerInfo, nlri bgp.AddrPrefixInterface, attrs []bgp.PathAttributeInterface, isWithdraw bool, now time.Time) (Path, error) {