summaryrefslogtreecommitdiffhomepage
path: root/policy
diff options
context:
space:
mode:
Diffstat (limited to 'policy')
-rw-r--r--policy/policy.go65
-rw-r--r--policy/policy_test.go409
2 files changed, 434 insertions, 40 deletions
diff --git a/policy/policy.go b/policy/policy.go
index 4f56fab6..49d210aa 100644
--- a/policy/policy.go
+++ b/policy/policy.go
@@ -791,28 +791,29 @@ func (a *CommunityAction) apply(path table.Path) table.Path {
type MedAction struct {
DefaultAction
- Value uint32
+ Value int64
action ActionType
}
const (
MED_ACTION_NONE ActionType = iota
+ MED_ACTION_REPLACE
MED_ACTION_ADD
MED_ACTION_SUB
-// MED_ACTION_IGP
)
-//const (
-// MED_IGP string = "IGP"
-//)
// NewMedAction creates MedAction object.
// If it cannot parse med string, then return nil.
-// Similarly, if option string is invalid, return nil.
func NewMedAction(med config.BgpSetMedType) *MedAction {
+ if med == ""{
+ return nil
+ }
+
m := &MedAction{}
- matched, value, action := getMedValue(fmt.Sprintf("%v", med))
+
+ matched, value, action := getMedValue(fmt.Sprintf("%s", med))
if !matched {
log.WithFields(log.Fields{
"Topic": "Policy",
@@ -826,59 +827,45 @@ func NewMedAction(med config.BgpSetMedType) *MedAction {
}
// getMedValue returns uint32 med value and action type (+ or -).
-// if the string doesn't match a number or operator or well known med name,
-// it returns false and 0 and MED_ACTION_NONE.
-func getMedValue(medStr string) (bool, uint32, ActionType) {
- regUint, _ := regexp.Compile("^([0-9]+)$")
- regUintAc, _ := regexp.Compile("^(\\+|\\-)([0-9]+)$")
-// regIGP, _ := regexp.Compile("^(IGP)$")
- if regUint.MatchString(medStr) {
- val, err := strconv.ParseUint(medStr, 10, 32)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Med Action",
- }).Error("failed to parser as number or med value.")
- }
- return true, uint32(val), MED_ACTION_NONE
- }
- if regUintAc.MatchString(medStr) {
- group := regUintAc.FindStringSubmatch(medStr)
- action := MED_ACTION_ADD
- if group[1] == "-" {
+// if the string doesn't match a number or operator,
+// it returns false and 0.
+func getMedValue(medStr string) (bool, int64, ActionType) {
+ regMed, _ := regexp.Compile("^(\\+|\\-)?([0-9]+)$")
+ if regMed.MatchString(medStr) {
+ group := regMed.FindStringSubmatch(medStr)
+ action := MED_ACTION_REPLACE
+ if group[1] == "+" {
+ action = MED_ACTION_ADD
+ } else if group[1] == "-" {
action = MED_ACTION_SUB
}
- val, err := strconv.ParseUint(group[2], 10, 32)
+ val, err := strconv.ParseInt(medStr, 10, 64)
if err != nil {
log.WithFields(log.Fields{
"Topic": "Policy",
"Type": "Med Action",
}).Error("failed to parser as number or med value.")
}
- return true, uint32(val), action
+ return true, int64(val), action
}
-// if regIGP.MatchString(medStr) {
-// return true, uint32(0), MED_IGP
-// }
- return false, uint32(0), MED_ACTION_NONE
+ return false, int64(0), MED_ACTION_NONE
}
-
func (a *MedAction) apply(path table.Path) table.Path {
var err error
switch a.action {
- case MED_ACTION_NONE:
- err = path.SetMed(a.Value, true, false)
+ case MED_ACTION_REPLACE:
+ err = path.SetMed(a.Value, true)
case MED_ACTION_ADD:
- err = path.SetMed(a.Value, false, false)
+ err = path.SetMed(a.Value, false)
case MED_ACTION_SUB:
- err = path.SetMed(a.Value, false, true)
+ err = path.SetMed(a.Value, false)
}
if err != nil {
log.WithFields(log.Fields{
"Topic": "Policy",
"Type": "Med Action",
- }).Error(err)
+ }).Warn(err)
}
return path
diff --git a/policy/policy_test.go b/policy/policy_test.go
index 2eced491..ebabb3c8 100644
--- a/policy/policy_test.go
+++ b/policy/policy_test.go
@@ -25,6 +25,8 @@ import (
"strconv"
"strings"
"testing"
+ "fmt"
+ "math"
)
func TestPrefixCalcurateNoRange(t *testing.T) {
@@ -1441,4 +1443,409 @@ func stringToCommunityValue(comStr string) uint32 {
asn, _ := strconv.ParseUint(elem[0], 10, 16)
val, _ := strconv.ParseUint(elem[1], 10, 16)
return uint32(asn<<16 | val)
-} \ No newline at end of file
+}
+
+func TestPolicyMatchAndReplaceMed(t *testing.T) {
+
+ // 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})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(100)
+
+ 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)
+ path := table.ProcessMessage(updateMsg, peer)[0]
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.0.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.0.1"),
+ }},
+ }
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ m := "200"
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL,
+ },
+ Actions: config.Actions{
+ AcceptRoute: true,
+ BgpActions: config.BgpActions{
+ SetMed: config.BgpSetMedType(m),
+ },
+ },
+ }
+
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
+ assert.NotEqual(t, nil, newPath)
+
+ newMed := fmt.Sprintf("%d", newPath.GetMed())
+ assert.Equal(t, m, newMed)
+}
+
+func TestPolicyMatchAndAddingMed(t *testing.T) {
+
+ // 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})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(100)
+
+ 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)
+ path := table.ProcessMessage(updateMsg, peer)[0]
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.0.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.0.1"),
+ }},
+ }
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ m := "+200"
+ ma := "300"
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL,
+ },
+ Actions: config.Actions{
+ AcceptRoute: true,
+ BgpActions: config.BgpActions{
+ SetMed: config.BgpSetMedType(m),
+ },
+ },
+ }
+
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
+ assert.NotEqual(t, nil, newPath)
+
+ newMed := fmt.Sprintf("%d", newPath.GetMed())
+ assert.Equal(t, ma, newMed)
+}
+
+func TestPolicyMatchAndAddingMedOverFlow(t *testing.T) {
+
+ // 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})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(1)
+
+ 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)
+ path := table.ProcessMessage(updateMsg, peer)[0]
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.0.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.0.1"),
+ }},
+ }
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ m := fmt.Sprintf("+%d",math.MaxUint32)
+ ma := "1"
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL,
+ },
+ Actions: config.Actions{
+ AcceptRoute: true,
+ BgpActions: config.BgpActions{
+ SetMed: config.BgpSetMedType(m),
+ },
+ },
+ }
+
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
+ assert.NotEqual(t, nil, newPath)
+
+ newMed := fmt.Sprintf("%d", newPath.GetMed())
+ assert.Equal(t, ma, newMed)
+}
+
+func TestPolicyMatchAndSubtractMed(t *testing.T) {
+
+ // 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})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(100)
+
+ 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)
+ path := table.ProcessMessage(updateMsg, peer)[0]
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.0.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.0.1"),
+ }},
+ }
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ m := "-50"
+ ma := "50"
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL,
+ },
+ Actions: config.Actions{
+ AcceptRoute: true,
+ BgpActions: config.BgpActions{
+ SetMed: config.BgpSetMedType(m),
+ },
+ },
+ }
+
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
+ assert.NotEqual(t, nil, newPath)
+
+ newMed := fmt.Sprintf("%d", newPath.GetMed())
+ assert.Equal(t, ma, newMed)
+}
+
+func TestPolicyMatchAndSubtractMedUnderFlow(t *testing.T) {
+
+ // 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})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+ med := bgp.NewPathAttributeMultiExitDisc(100)
+
+ 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)
+ path := table.ProcessMessage(updateMsg, peer)[0]
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.0.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.0.1"),
+ }},
+ }
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ m := "-101"
+ ma := "100"
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL,
+ },
+ Actions: config.Actions{
+ AcceptRoute: true,
+ BgpActions: config.BgpActions{
+ SetMed: config.BgpSetMedType(m),
+ },
+ },
+ }
+
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
+ assert.NotEqual(t, nil, newPath)
+
+ newMed := fmt.Sprintf("%d", newPath.GetMed())
+ assert.Equal(t, ma, newMed)
+}
+
+func TestPolicyMatchWhenPathHaveNotMed(t *testing.T) {
+
+ // 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})}
+ aspath := bgp.NewPathAttributeAsPath(aspathParam)
+ nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
+
+ pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop}
+ nlri := []bgp.NLRInfo{*bgp.NewNLRInfo(24, "10.10.0.101")}
+ withdrawnRoutes := []bgp.WithdrawnRoute{}
+ updateMsg := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
+ path := table.ProcessMessage(updateMsg, peer)[0]
+ // create policy
+ ps := config.PrefixSet{
+ PrefixSetName: "ps1",
+ PrefixList: []config.Prefix{
+ config.Prefix{
+ Address: net.ParseIP("10.10.0.0"),
+ Masklength: 16,
+ MasklengthRange: "21..24",
+ }},
+ }
+ ns := config.NeighborSet{
+ NeighborSetName: "ns1",
+ NeighborInfoList: []config.NeighborInfo{
+ config.NeighborInfo{
+ Address: net.ParseIP("10.0.0.1"),
+ }},
+ }
+ ds := config.DefinedSets{
+ PrefixSetList: []config.PrefixSet{ps},
+ NeighborSetList: []config.NeighborSet{ns},
+ }
+
+ m := "-50"
+ s := config.Statement{
+ Name: "statement1",
+ Conditions: config.Conditions{
+ MatchPrefixSet: "ps1",
+ MatchNeighborSet: "ns1",
+ MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ALL,
+ },
+ Actions: config.Actions{
+ AcceptRoute: true,
+ BgpActions: config.BgpActions{
+ SetMed: config.BgpSetMedType(m),
+ },
+ },
+ }
+
+ pd := config.PolicyDefinition{"pd1", []config.Statement{s}}
+ pl := config.RoutingPolicy{ds, []config.PolicyDefinition{pd}}
+ //test
+ df := pl.DefinedSets
+ p := NewPolicy(pl.PolicyDefinitionList[0], df)
+ match, pType, newPath := p.Apply(path)
+ assert.Equal(t, true, match)
+ assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
+ assert.NotEqual(t, nil, newPath)
+
+ newMed := fmt.Sprintf("%d", newPath.GetMed())
+ assert.Equal(t, "0", newMed)
+}