summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--policy/policy.go44
-rw-r--r--policy/policy_test.go330
2 files changed, 354 insertions, 20 deletions
diff --git a/policy/policy.go b/policy/policy.go
index b35e765f..b641b7a4 100644
--- a/policy/policy.go
+++ b/policy/policy.go
@@ -712,7 +712,7 @@ type ExtCommunityElement struct {
}
func NewExtCommunityCondition(extComSetName string, defExtComSetList []config.ExtCommunitySet) *ExtCommunityCondition {
- extCommunityList := make([]*ExtCommunityElement, 0)
+ extCommunityElemList := make([]*ExtCommunityElement, 0)
for _, extComSet := range defExtComSetList {
if extComSet.ExtCommunitySetName == extComSetName {
for _, c := range extComSet.ExtCommunityMembers {
@@ -753,22 +753,22 @@ func NewExtCommunityCondition(extComSetName string, defExtComSetList []config.Ex
matchAll = true
}
}
- if !matchAll{
+ if !matchAll {
e.isRegExp = true
- reg, err := regexp.Compile(val[2])
+ reg, err := regexp.Compile(c)
if err != nil {
log.WithFields(log.Fields{
"Topic": "Policy",
"Type": "Community Condition",
- }).Errorf("Regular expression can't be compiled %d.", val[2])
+ }).Errorf("Regular expression can't be compiled %s.", val[2])
return nil
}
e.regExp = reg
}
- extCommunityList = append(extCommunityList, e)
+ extCommunityElemList = append(extCommunityElemList, e)
}
ce := &ExtCommunityCondition{
- ExtCommunityList: extCommunityList,
+ ExtCommunityList: extCommunityElemList,
}
return ce
}
@@ -829,26 +829,35 @@ func getECommunityElem(gAdmin string) (bool, bgp.ExtendedCommunityAttrType, inte
// compare extended community in the message's attribute with
// the one in the condition.
func (c *ExtCommunityCondition) evaluate(path *table.Path) bool {
-
- makeStr := func(ec *ExtCommunityElement) string {
+ makeAs4Str := func(ec *ExtCommunityElement) string {
t := ec.ecType
str := fmt.Sprintf("%d", ec.localAdmin)
switch t {
case bgp.EC_TYPE_TRANSITIVE_TWO_OCTET_AS_SPECIFIC:
- str = fmt.Sprintf("%d:%d", ec.globalAdmin.(uint16), str)
+ str = fmt.Sprintf("%d:%s", ec.globalAdmin.(uint16), str)
case bgp.EC_TYPE_TRANSITIVE_IP4_SPECIFIC:
- str = fmt.Sprintf("%s:%d", ec.globalAdmin.(net.IP).String(), str)
+ str = fmt.Sprintf("%s:%s", ec.globalAdmin.(net.IP).String(), str)
case bgp.EC_TYPE_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC:
ga := ec.globalAdmin.(uint32)
upper := strconv.FormatUint(uint64(ga&0xFFFF0000>>16), 10)
lower := strconv.FormatUint(uint64(ga&0x0000FFFF), 10)
- str = fmt.Sprintf("%d.%d:%s", upper, lower, str)
+ str = fmt.Sprintf("%s.%s:%s", upper, lower, str)
}
return str
}
+ makeTypeSubStr := func(st bgp.ExtendedCommunityAttrSubType) string {
+ subStr := ""
+ switch st {
+ case bgp.EC_SUBTYPE_ROUTE_TARGET:
+ subStr = "RT"
+ case bgp.EC_SUBTYPE_ROUTE_ORIGIN:
+ subStr = "SoO"
+ }
+ return subStr
+ }
eCommunities := path.GetExtCommunities()
- if len(eCommunities) == 0 {
+ if len(eCommunities) == 0 || c == nil {
return false
}
@@ -859,11 +868,9 @@ func (c *ExtCommunityCondition) evaluate(path *table.Path) bool {
for _, eCommunity := range eCommunities {
ec := eCommunity.(bgp.ExtendedCommunityInterface)
t, st := ec.GetTypes()
- if member.ecType != t || member.ecSubType != st {
- continue
- }
if member.isRegExp {
- if member.regExp.MatchString(ec.String()) {
+ ecString := fmt.Sprintf("%s:%s", makeTypeSubStr(st), ec.String())
+ if member.regExp.MatchString(ecString) {
matched = true
log.WithFields(log.Fields{
"Topic": "Policy",
@@ -872,12 +879,13 @@ func (c *ExtCommunityCondition) evaluate(path *table.Path) bool {
matchStr = ec.String()
break
}
- } else {
- if makeStr(member) == ec.String() {
+ } else if member.ecType == t && member.ecSubType == st {
+ if makeAs4Str(member) == ec.String() {
matched = true
matchStr = ec.String()
break
}
+
}
}
if matched {
diff --git a/policy/policy_test.go b/policy/policy_test.go
index d1155335..389ca31e 100644
--- a/policy/policy_test.go
+++ b/policy/policy_test.go
@@ -924,7 +924,7 @@ func TestAsPathConditionWithOtherCondition(t *testing.T) {
}
-func TestConditionConditionEvaluate(t *testing.T) {
+func TestCommunityConditionEvaluate(t *testing.T) {
log.SetLevel(log.DebugLevel)
@@ -1020,7 +1020,7 @@ func TestConditionConditionEvaluate(t *testing.T) {
}
-func TestConditionConditionEvaluateWithOtherCondition(t *testing.T) {
+func TestCommunityConditionEvaluateWithOtherCondition(t *testing.T) {
log.SetLevel(log.DebugLevel)
@@ -1443,6 +1443,332 @@ func stringToCommunityValue(comStr string) uint32 {
return uint32(asn<<16 | val)
}
+func TestExtCommunityConditionEvaluate(t *testing.T) {
+
+ log.SetLevel(log.DebugLevel)
+
+ // setup
+ // create path
+ peer := &table.PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
+ origin := bgp.NewPathAttributeOrigin(0)
+ aspathParam1 := []bgp.AsPathParamInterface{
+ bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 65005}),
+ bgp.NewAsPathParam(1, []uint16{65001, 65010, 65004, 65005}),
+ }
+ aspath := bgp.NewPathAttributeAsPath(aspathParam1)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(0)
+ eComAsSpecific1 := &bgp.TwoOctetAsSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ AS: 65001,
+ LocalAdmin: 200,
+ IsTransitive: true,
+ }
+ eComIpPrefix1 := &bgp.IPv4AddressSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ IPv4: net.ParseIP("10.0.0.1"),
+ LocalAdmin: 300,
+ IsTransitive: true,
+ }
+ eComAs4Specific1 := &bgp.FourOctetAsSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ AS: 65030000,
+ LocalAdmin: 200,
+ IsTransitive: true,
+ }
+ eComAsSpecific2 := &bgp.TwoOctetAsSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ AS: 65002,
+ LocalAdmin: 200,
+ IsTransitive: false,
+ }
+ eComIpPrefix2 := &bgp.IPv4AddressSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ IPv4: net.ParseIP("10.0.0.2"),
+ LocalAdmin: 300,
+ IsTransitive: false,
+ }
+ eComAs4Specific2 := &bgp.FourOctetAsSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ AS: 65030001,
+ LocalAdmin: 200,
+ IsTransitive: false,
+ }
+ eComAsSpecific3 := &bgp.TwoOctetAsSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_ORIGIN),
+ AS: 65010,
+ LocalAdmin: 300,
+ IsTransitive: true,
+ }
+ eComIpPrefix3 := &bgp.IPv4AddressSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_ORIGIN),
+ IPv4: net.ParseIP("10.0.10.10"),
+ LocalAdmin: 400,
+ IsTransitive: true,
+ }
+ eComAs4Specific3 := &bgp.FourOctetAsSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ AS: 65030002,
+ LocalAdmin: 500,
+ IsTransitive: true,
+ }
+ ec := []bgp.ExtendedCommunityInterface{eComAsSpecific1, eComIpPrefix1, eComAs4Specific1, eComAsSpecific2,
+ eComIpPrefix2, eComAs4Specific2, eComAsSpecific3, eComIpPrefix3, eComAs4Specific3}
+ extCommunities := bgp.NewPathAttributeExtendedCommunities(ec)
+
+ pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, extCommunities}
+ nlri := []bgp.NLRInfo{*bgp.NewNLRInfo(24, "10.10.0.101")}
+ withdrawnRoutes := []bgp.WithdrawnRoute{}
+ updateMsg1 := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
+ table.UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate))
+ path1 := table.ProcessMessage(updateMsg1, peer)[0]
+
+ convUintStr := func(as uint32) string {
+ upper := strconv.FormatUint(uint64(as&0xFFFF0000>>16), 10)
+ lower := strconv.FormatUint(uint64(as&0x0000FFFF), 10)
+ str := fmt.Sprintf("%s.%s", upper, lower)
+ return str
+ }
+
+ // create match condition
+ ecomSet1 := config.ExtCommunitySet{
+ ExtCommunitySetName: "ecomSet1",
+ ExtCommunityMembers: []string{"RT:65001:200"},
+ }
+ ecomSet2 := config.ExtCommunitySet{
+ ExtCommunitySetName: "ecomSet2",
+ ExtCommunityMembers: []string{"RT:10.0.0.1:300"},
+ }
+ ecomSet3 := config.ExtCommunitySet{
+ ExtCommunitySetName: "ecomSet3",
+ ExtCommunityMembers: []string{fmt.Sprintf("RT:%s:200", convUintStr(65030000))},
+ }
+ ecomSet4 := config.ExtCommunitySet{
+ ExtCommunitySetName: "ecomSet4",
+ ExtCommunityMembers: []string{"RT:65002:200"},
+ }
+ ecomSet5 := config.ExtCommunitySet{
+ ExtCommunitySetName: "ecomSet5",
+ ExtCommunityMembers: []string{"RT:10.0.0.2:300"},
+ }
+ ecomSet6 := config.ExtCommunitySet{
+ ExtCommunitySetName: "ecomSet6",
+ ExtCommunityMembers: []string{fmt.Sprintf("RT:%s:200", convUintStr(65030001))},
+ }
+ ecomSet7 := config.ExtCommunitySet{
+ ExtCommunitySetName: "ecomSet7",
+ ExtCommunityMembers: []string{"SoO:65010:300"},
+ }
+ ecomSet8 := config.ExtCommunitySet{
+ ExtCommunitySetName: "ecomSet8",
+ ExtCommunityMembers: []string{"SoO:10.0.10.10:[0-9]+"},
+ }
+ ecomSet9 := config.ExtCommunitySet{
+ ExtCommunitySetName: "ecomSet9",
+ ExtCommunityMembers: []string{"RT:[0-9]+:[0-9]+"},
+ }
+ comSetList := []config.ExtCommunitySet{ecomSet1, ecomSet2, ecomSet3, ecomSet4, ecomSet5, ecomSet6, ecomSet7,
+ ecomSet8, ecomSet9}
+ p1 := NewExtCommunityCondition("ecomSet1", comSetList)
+ p2 := NewExtCommunityCondition("ecomSet2", comSetList)
+ p3 := NewExtCommunityCondition("ecomSet3", comSetList)
+ p4 := NewExtCommunityCondition("ecomSet4", comSetList)
+ p5 := NewExtCommunityCondition("ecomSet5", comSetList)
+ p6 := NewExtCommunityCondition("ecomSet6", comSetList)
+ p7 := NewExtCommunityCondition("ecomSet7", comSetList)
+ p8 := NewExtCommunityCondition("ecomSet8", comSetList)
+ p9 := NewExtCommunityCondition("ecomSet9", comSetList)
+ // test
+ assert.Equal(t, true, p1.evaluate(path1))
+ assert.Equal(t, true, p2.evaluate(path1))
+ assert.Equal(t, true, p3.evaluate(path1))
+ assert.Equal(t, false, p4.evaluate(path1))
+ assert.Equal(t, false, p5.evaluate(path1))
+ assert.Equal(t, false, p6.evaluate(path1))
+ assert.Equal(t, true, p7.evaluate(path1))
+ assert.Equal(t, true, p8.evaluate(path1))
+ assert.Equal(t, true, p9.evaluate(path1))
+}
+
+func TestExtCommunityConditionEvaluateWithOtherCondition(t *testing.T) {
+
+ log.SetLevel(log.DebugLevel)
+
+ // 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)
+ eComAsSpecific1 := &bgp.TwoOctetAsSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ AS: 65001,
+ LocalAdmin: 200,
+ IsTransitive: true,
+ }
+ eComIpPrefix1 := &bgp.IPv4AddressSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ IPv4: net.ParseIP("10.0.0.1"),
+ LocalAdmin: 300,
+ IsTransitive: true,
+ }
+ eComAs4Specific1 := &bgp.FourOctetAsSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ AS: 65030000,
+ LocalAdmin: 200,
+ IsTransitive: true,
+ }
+ eComAsSpecific2 := &bgp.TwoOctetAsSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ AS: 65002,
+ LocalAdmin: 200,
+ IsTransitive: false,
+ }
+ eComIpPrefix2 := &bgp.IPv4AddressSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ IPv4: net.ParseIP("10.0.0.2"),
+ LocalAdmin: 300,
+ IsTransitive: false,
+ }
+ eComAs4Specific2 := &bgp.FourOctetAsSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ AS: 65030001,
+ LocalAdmin: 200,
+ IsTransitive: false,
+ }
+ eComAsSpecific3 := &bgp.TwoOctetAsSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_ORIGIN),
+ AS: 65010,
+ LocalAdmin: 300,
+ IsTransitive: true,
+ }
+ eComIpPrefix3 := &bgp.IPv4AddressSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_ORIGIN),
+ IPv4: net.ParseIP("10.0.10.10"),
+ LocalAdmin: 400,
+ IsTransitive: true,
+ }
+ eComAs4Specific3 := &bgp.FourOctetAsSpecificExtended{
+ SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
+ AS: 65030002,
+ LocalAdmin: 500,
+ IsTransitive: true,
+ }
+ ec := []bgp.ExtendedCommunityInterface{eComAsSpecific1, eComIpPrefix1, eComAs4Specific1, eComAsSpecific2,
+ eComIpPrefix2, eComAs4Specific2, eComAsSpecific3, eComIpPrefix3, eComAs4Specific3}
+ extCommunities := bgp.NewPathAttributeExtendedCommunities(ec)
+
+ pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, extCommunities}
+ 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))
+ path := table.ProcessMessage(updateMsg, peer)[0]
+
+ // create policy
+ asPathSet := config.AsPathSet{
+ AsPathSetName: "asset1",
+ AsPathSetMembers: []string{"65004$"},
+ }
+
+ ecomSet1 := config.ExtCommunitySet{
+ ExtCommunitySetName: "ecomSet1",
+ ExtCommunityMembers: []string{"RT:65001:201"},
+ }
+ ecomSet2 := config.ExtCommunitySet{
+ ExtCommunitySetName: "ecomSet2",
+ ExtCommunityMembers: []string{"RT:[0-9]+:[0-9]+"},
+ }
+
+ prefixSet := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.11.1.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+
+ neighborSet := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.2.1.1"),
+ }},
+ }
+
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{prefixSet},
+ NeighborSetList: []config.NeighborSet{neighborSet},
+ BgpDefinedSets: config.BgpDefinedSets{
+ AsPathSetList: []config.AsPathSet{asPathSet},
+ ExtCommunitySetList: []config.ExtCommunitySet{ecomSet1, ecomSet2},
+ },
+ }
+
+ s1 := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ BgpConditions: config.BgpConditions{
+ MatchAsPathSet: "asset1",
+ MatchExtCommunitySet: "ecomSet1",
+ },
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY,
+ },
+ Actions: config.Actions{
+ AcceptRoute: false,
+ RejectRoute: true,
+ },
+ }
+
+ s2 := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ BgpConditions: config.BgpConditions{
+ MatchAsPathSet: "asset1",
+ MatchExtCommunitySet: "ecomSet2",
+ },
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY,
+ },
+ Actions: config.Actions{
+ AcceptRoute: false,
+ RejectRoute: true,
+ },
+ }
+
+ pd1 := config.PolicyDefinition{"pd1", []config.Statement{s1}}
+ pd2 := config.PolicyDefinition{"pd2", []config.Statement{s2}}
+ pl := config.RoutingPolicy{
+ DefinedSets: ds,
+ PolicyDefinitionList: []config.PolicyDefinition{pd1, pd2},
+ }
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, false, match)
+ assert.Equal(t, ROUTE_TYPE_NONE, pType)
+ assert.Nil(t, newPath)
+
+ df = pl.DefinedSets
+ p = NewPolicy(pl.PolicyDefinitionList[1], df)
+ match, pType, newPath = p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_REJECT, pType)
+ assert.Nil(t, newPath)
+
+}
+
func TestPolicyMatchAndReplaceMed(t *testing.T) {
// create path