diff options
Diffstat (limited to 'internal/pkg/table/policy_test.go')
-rw-r--r-- | internal/pkg/table/policy_test.go | 3140 |
1 files changed, 3140 insertions, 0 deletions
diff --git a/internal/pkg/table/policy_test.go b/internal/pkg/table/policy_test.go new file mode 100644 index 00000000..7f1a1dd9 --- /dev/null +++ b/internal/pkg/table/policy_test.go @@ -0,0 +1,3140 @@ +// Copyright (C) 2014,2015 Nippon Telegraph and Telephone Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package table + +import ( + "fmt" + "math" + "net" + "strconv" + "strings" + "testing" + "time" + + "github.com/osrg/gobgp/internal/pkg/config" + "github.com/osrg/gobgp/pkg/packet/bgp" + + log "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestPrefixCalcurateNoRange(t *testing.T) { + // create path + peer := &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(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.0")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // test + pl1, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/24", MasklengthRange: ""}) + match1 := pl1.Match(path) + assert.Equal(t, true, match1) + pl2, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/23", MasklengthRange: ""}) + match2 := pl2.Match(path) + assert.Equal(t, false, match2) + pl3, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/16", MasklengthRange: "21..24"}) + match3 := pl3.Match(path) + assert.Equal(t, true, match3) +} + +func TestPrefixCalcurateAddress(t *testing.T) { + // create path + peer := &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(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // test + pl1, _ := NewPrefix(config.Prefix{IpPrefix: "10.11.0.0/16", MasklengthRange: "21..24"}) + match1 := pl1.Match(path) + assert.Equal(t, false, match1) + pl2, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/16", MasklengthRange: "21..24"}) + match2 := pl2.Match(path) + assert.Equal(t, true, match2) +} + +func TestPrefixCalcurateLength(t *testing.T) { + // create path + peer := &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(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // test + pl1, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.64.0/24", MasklengthRange: "21..24"}) + match1 := pl1.Match(path) + assert.Equal(t, false, match1) + pl2, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.64.0/16", MasklengthRange: "21..24"}) + match2 := pl2.Match(path) + assert.Equal(t, true, match2) +} + +func TestPrefixCalcurateLengthRange(t *testing.T) { + // create path + peer := &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(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // test + pl1, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/16", MasklengthRange: "21..23"}) + match1 := pl1.Match(path) + assert.Equal(t, false, match1) + pl2, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/16", MasklengthRange: "25..26"}) + match2 := pl2.Match(path) + assert.Equal(t, false, match2) + pl3, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/16", MasklengthRange: "21..24"}) + match3 := pl3.Match(path) + assert.Equal(t, true, match3) +} + +func TestPrefixCalcurateNoRangeIPv6(t *testing.T) { + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("2001::192:168:50:1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})} + aspath := bgp.NewPathAttributeAsPath(aspathParam) + mpnlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")} + mpreach := bgp.NewPathAttributeMpReachNLRI("2001::192:168:50:1", mpnlri) + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{mpreach, origin, aspath, med} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nil) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // test + pl1, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123::/48", MasklengthRange: ""}) + match1 := pl1.Match(path) + assert.Equal(t, false, match1) + pl2, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123:1::/64", MasklengthRange: ""}) + match2 := pl2.Match(path) + assert.Equal(t, true, match2) + pl3, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123::/48", MasklengthRange: "64..80"}) + match3 := pl3.Match(path) + assert.Equal(t, true, match3) +} + +func TestPrefixCalcurateAddressIPv6(t *testing.T) { + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("2001::192:168:50:1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})} + aspath := bgp.NewPathAttributeAsPath(aspathParam) + mpnlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")} + mpreach := bgp.NewPathAttributeMpReachNLRI("2001::192:168:50:1", mpnlri) + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{mpreach, origin, aspath, med} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nil) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // test + pl1, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:128::/48", MasklengthRange: "64..80"}) + match1 := pl1.Match(path) + assert.Equal(t, false, match1) + pl2, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123::/48", MasklengthRange: "64..80"}) + match2 := pl2.Match(path) + assert.Equal(t, true, match2) +} + +func TestPrefixCalcurateLengthIPv6(t *testing.T) { + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("2001::192:168:50:1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})} + aspath := bgp.NewPathAttributeAsPath(aspathParam) + mpnlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")} + mpreach := bgp.NewPathAttributeMpReachNLRI("2001::192:168:50:1", mpnlri) + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{mpreach, origin, aspath, med} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nil) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // test + pl1, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123:64::/64", MasklengthRange: "64..80"}) + match1 := pl1.Match(path) + assert.Equal(t, false, match1) + pl2, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123:64::/48", MasklengthRange: "64..80"}) + match2 := pl2.Match(path) + assert.Equal(t, true, match2) +} + +func TestPrefixCalcurateLengthRangeIPv6(t *testing.T) { + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("2001::192:168:50:1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})} + aspath := bgp.NewPathAttributeAsPath(aspathParam) + mpnlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")} + mpreach := bgp.NewPathAttributeMpReachNLRI("2001::192:168:50:1", mpnlri) + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{mpreach, origin, aspath, med} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nil) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // test + pl1, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123::/48", MasklengthRange: "62..63"}) + match1 := pl1.Match(path) + assert.Equal(t, false, match1) + pl2, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123::/48", MasklengthRange: "65..66"}) + match2 := pl2.Match(path) + assert.Equal(t, false, match2) + pl3, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123::/48", MasklengthRange: "63..65"}) + match3 := pl3.Match(path) + assert.Equal(t, true, match3) +} + +func TestPolicyNotMatch(t *testing.T) { + // create path + peer := &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(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ps := createPrefixSet("ps1", "10.3.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + s := createStatement("statement1", "ps1", "ns1", false) + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + pType, newPath := r.policyMap["pd1"].Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_NONE, pType) + assert.Equal(t, newPath, path) +} + +func TestPolicyMatchAndReject(t *testing.T) { + // create path + peer := &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(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + s := createStatement("statement1", "ps1", "ns1", false) + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + pType, newPath := r.policyMap["pd1"].Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_REJECT, pType) + assert.Equal(t, newPath, path) +} + +func TestPolicyMatchAndAccept(t *testing.T) { + // create path + peer := &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(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + s := createStatement("statement1", "ps1", "ns1", true) + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + pType, newPath := r.policyMap["pd1"].Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.Equal(t, path, newPath) +} + +func TestPolicyRejectOnlyPrefixSet(t *testing.T) { + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.1.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})} + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.1.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.1.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path1 := ProcessMessage(updateMsg, peer, time.Now())[0] + + peer = &PeerInfo{AS: 65002, Address: net.ParseIP("10.0.2.2")} + origin = bgp.NewPathAttributeOrigin(0) + aspathParam = []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65002})} + aspath = bgp.NewPathAttributeAsPath(aspathParam) + nexthop = bgp.NewPathAttributeNextHop("10.0.2.2") + med = bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes = []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri = []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.9.2.102")} + updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path2 := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ps := createPrefixSet("ps1", "10.10.1.0/16", "21..24") + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + + s := createStatement("statement1", "ps1", "", false) + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + pType, newPath := p.Apply(path1, nil) + assert.Equal(t, ROUTE_TYPE_REJECT, pType) + assert.Equal(t, newPath, path1) + + pType2, newPath2 := p.Apply(path2, nil) + assert.Equal(t, ROUTE_TYPE_NONE, pType2) + assert.Equal(t, newPath2, path2) +} + +func TestPolicyRejectOnlyNeighborSet(t *testing.T) { + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.1.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})} + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.1.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.1.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path1 := ProcessMessage(updateMsg, peer, time.Now())[0] + + peer = &PeerInfo{AS: 65002, Address: net.ParseIP("10.0.2.2")} + origin = bgp.NewPathAttributeOrigin(0) + aspathParam = []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65002})} + aspath = bgp.NewPathAttributeAsPath(aspathParam) + nexthop = bgp.NewPathAttributeNextHop("10.0.2.2") + med = bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes = []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri = []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.2.102")} + updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path2 := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ns := createNeighborSet("ns1", "10.0.1.1") + ds := config.DefinedSets{} + ds.NeighborSets = []config.NeighborSet{ns} + + s := createStatement("statement1", "", "ns1", false) + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + pType, newPath := r.policyMap["pd1"].Apply(path1, nil) + assert.Equal(t, ROUTE_TYPE_REJECT, pType) + assert.Equal(t, newPath, path1) + + pType2, newPath2 := r.policyMap["pd1"].Apply(path2, nil) + assert.Equal(t, ROUTE_TYPE_NONE, pType2) + assert.Equal(t, newPath2, path2) +} + +func TestPolicyDifferentRoutefamilyOfPathAndPolicy(t *testing.T) { + // create path ipv4 + peerIPv4 := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + originIPv4 := bgp.NewPathAttributeOrigin(0) + aspathParamIPv4 := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})} + aspathIPv4 := bgp.NewPathAttributeAsPath(aspathParamIPv4) + nexthopIPv4 := bgp.NewPathAttributeNextHop("10.0.0.1") + medIPv4 := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributesIPv4 := []bgp.PathAttributeInterface{originIPv4, aspathIPv4, nexthopIPv4, medIPv4} + nlriIPv4 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsgIPv4 := bgp.NewBGPUpdateMessage(nil, pathAttributesIPv4, nlriIPv4) + pathIPv4 := ProcessMessage(updateMsgIPv4, peerIPv4, time.Now())[0] + // create path ipv6 + peerIPv6 := &PeerInfo{AS: 65001, Address: net.ParseIP("2001::192:168:50:1")} + originIPv6 := bgp.NewPathAttributeOrigin(0) + aspathParamIPv6 := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})} + aspathIPv6 := bgp.NewPathAttributeAsPath(aspathParamIPv6) + mpnlriIPv6 := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")} + mpreachIPv6 := bgp.NewPathAttributeMpReachNLRI("2001::192:168:50:1", mpnlriIPv6) + medIPv6 := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributesIPv6 := []bgp.PathAttributeInterface{mpreachIPv6, originIPv6, aspathIPv6, medIPv6} + updateMsgIPv6 := bgp.NewBGPUpdateMessage(nil, pathAttributesIPv6, nil) + pathIPv6 := ProcessMessage(updateMsgIPv6, peerIPv6, time.Now())[0] + // create policy + psIPv4 := createPrefixSet("psIPv4", "10.10.0.0/16", "21..24") + nsIPv4 := createNeighborSet("nsIPv4", "10.0.0.1") + + psIPv6 := createPrefixSet("psIPv6", "2001:123:123::/48", "64..80") + nsIPv6 := createNeighborSet("nsIPv6", "2001::192:168:50:1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{psIPv4, psIPv6} + ds.NeighborSets = []config.NeighborSet{nsIPv4, nsIPv6} + + stIPv4 := createStatement("statement1", "psIPv4", "nsIPv4", false) + stIPv6 := createStatement("statement2", "psIPv6", "nsIPv6", false) + + pd := createPolicyDefinition("pd1", stIPv4, stIPv6) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + pType1, newPath1 := p.Apply(pathIPv4, nil) + assert.Equal(t, ROUTE_TYPE_REJECT, pType1) + assert.Equal(t, newPath1, pathIPv4) + + pType2, newPath2 := p.Apply(pathIPv6, nil) + assert.Equal(t, ROUTE_TYPE_REJECT, pType2) + assert.Equal(t, newPath2, pathIPv6) +} + +func TestAsPathLengthConditionEvaluate(t *testing.T) { + // setup + // create path + peer := &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.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate)) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create match condition + asPathLength := config.AsPathLength{ + Operator: "eq", + Value: 5, + } + c, _ := NewAsPathLengthCondition(asPathLength) + + // test + assert.Equal(t, true, c.Evaluate(path, nil)) + + // create match condition + asPathLength = config.AsPathLength{ + Operator: "ge", + Value: 3, + } + c, _ = NewAsPathLengthCondition(asPathLength) + + // test + assert.Equal(t, true, c.Evaluate(path, nil)) + + // create match condition + asPathLength = config.AsPathLength{ + Operator: "le", + Value: 3, + } + c, _ = NewAsPathLengthCondition(asPathLength) + + // test + assert.Equal(t, false, c.Evaluate(path, nil)) +} + +func TestPolicyMatchAndAcceptNextHop(t *testing.T) { + // create path + peer := &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(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + s := createStatement("statement1", "ps1", "ns1", true) + s.Conditions.BgpConditions.NextHopInList = []string{"10.0.0.1/32"} + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + pType, newPath := r.policyMap["pd1"].Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.Equal(t, newPath, path) +} + +func TestPolicyMatchAndRejectNextHop(t *testing.T) { + // create path + peer := &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(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + s := createStatement("statement1", "ps1", "ns1", true) + s.Conditions.BgpConditions.NextHopInList = []string{"10.0.0.12"} + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + pType, newPath := r.policyMap["pd1"].Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_NONE, pType) + assert.Equal(t, newPath, path) +} + +func TestAsPathLengthConditionWithOtherCondition(t *testing.T) { + // setup + // create path + peer := &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.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate)) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ps := createPrefixSet("ps1", "10.10.1.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + // create match condition + asPathLength := config.AsPathLength{ + Operator: "le", + Value: 10, + } + + s := createStatement("statement1", "ps1", "ns1", false) + s.Conditions.BgpConditions.AsPathLength = asPathLength + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_REJECT, pType) + assert.Equal(t, newPath, path) + +} + +func TestAs4PathLengthConditionEvaluate(t *testing.T) { + // setup + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{ + bgp.NewAs4PathParam(2, []uint32{ + createAs4Value("65001.1"), + createAs4Value("65000.1"), + createAs4Value("65004.1"), + createAs4Value("65005.1"), + }), + bgp.NewAs4PathParam(1, []uint32{ + createAs4Value("65001.1"), + createAs4Value("65000.1"), + createAs4Value("65004.1"), + createAs4Value("65005.1"), + }), + } + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate)) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create match condition + asPathLength := config.AsPathLength{ + Operator: "eq", + Value: 5, + } + c, _ := NewAsPathLengthCondition(asPathLength) + + // test + assert.Equal(t, true, c.Evaluate(path, nil)) + + // create match condition + asPathLength = config.AsPathLength{ + Operator: "ge", + Value: 3, + } + c, _ = NewAsPathLengthCondition(asPathLength) + + // test + assert.Equal(t, true, c.Evaluate(path, nil)) + + // create match condition + asPathLength = config.AsPathLength{ + Operator: "le", + Value: 3, + } + c, _ = NewAsPathLengthCondition(asPathLength) + + // test + assert.Equal(t, false, c.Evaluate(path, nil)) +} + +func addPolicy(r *RoutingPolicy, x *Policy) { + for _, s := range x.Statements { + for _, c := range s.Conditions { + r.validateCondition(c) + } + } +} + +func TestAs4PathLengthConditionWithOtherCondition(t *testing.T) { + // setup + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{ + bgp.NewAs4PathParam(2, []uint32{ + createAs4Value("65001.1"), + createAs4Value("65000.1"), + createAs4Value("65004.1"), + createAs4Value("65004.1"), + createAs4Value("65005.1"), + }), + bgp.NewAs4PathParam(1, []uint32{ + createAs4Value("65001.1"), + createAs4Value("65000.1"), + createAs4Value("65004.1"), + createAs4Value("65005.1"), + }), + } + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate)) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ps := createPrefixSet("ps1", "10.10.1.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + // create match condition + asPathLength := config.AsPathLength{ + Operator: "le", + Value: 10, + } + + s := createStatement("statement1", "ps1", "ns1", false) + s.Conditions.BgpConditions.AsPathLength = asPathLength + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + r.reload(pl) + p, _ := NewPolicy(pl.PolicyDefinitions[0]) + addPolicy(r, p) + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_REJECT, pType) + assert.Equal(t, newPath, path) + +} + +func TestAsPathConditionEvaluate(t *testing.T) { + + // setup + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam1 := []bgp.AsPathParamInterface{ + bgp.NewAsPathParam(2, []uint16{65001, 65000, 65010, 65004, 65005}), + } + aspath := bgp.NewPathAttributeAsPath(aspathParam1) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate)) + path1 := ProcessMessage(updateMsg1, peer, time.Now())[0] + + aspathParam2 := []bgp.AsPathParamInterface{ + bgp.NewAsPathParam(2, []uint16{65010}), + } + aspath2 := bgp.NewPathAttributeAsPath(aspathParam2) + pathAttributes = []bgp.PathAttributeInterface{origin, aspath2, nexthop, med} + updateMsg2 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg2.Body.(*bgp.BGPUpdate)) + path2 := ProcessMessage(updateMsg2, peer, time.Now())[0] + + // create match condition + asPathSet1 := config.AsPathSet{ + AsPathSetName: "asset1", + AsPathList: []string{"^65001"}, + } + + asPathSet2 := config.AsPathSet{ + AsPathSetName: "asset2", + AsPathList: []string{"65005$"}, + } + + asPathSet3 := config.AsPathSet{ + AsPathSetName: "asset3", + AsPathList: []string{"65004", "65005$"}, + } + + asPathSet4 := config.AsPathSet{ + AsPathSetName: "asset4", + AsPathList: []string{"65000$"}, + } + + asPathSet5 := config.AsPathSet{ + AsPathSetName: "asset5", + AsPathList: []string{"65010"}, + } + + asPathSet6 := config.AsPathSet{ + AsPathSetName: "asset6", + AsPathList: []string{"^65010$"}, + } + + m := make(map[string]DefinedSet) + for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3, + asPathSet4, asPathSet5, asPathSet6} { + a, _ := NewAsPathSet(s) + m[s.AsPathSetName] = a + } + + createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition { + matchSet := config.MatchAsPathSet{} + matchSet.AsPathSet = name + matchSet.MatchSetOptions = option + p, _ := NewAsPathCondition(matchSet) + if v, ok := m[name]; ok { + p.set = v.(*AsPathSet) + } + return p + } + + p1 := createAspathC("asset1", config.MATCH_SET_OPTIONS_TYPE_ANY) + p2 := createAspathC("asset2", config.MATCH_SET_OPTIONS_TYPE_ANY) + p3 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ANY) + p4 := createAspathC("asset4", config.MATCH_SET_OPTIONS_TYPE_ANY) + p5 := createAspathC("asset5", config.MATCH_SET_OPTIONS_TYPE_ANY) + p6 := createAspathC("asset6", config.MATCH_SET_OPTIONS_TYPE_ANY) + p7 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ALL) + p8 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_INVERT) + + // test + assert.Equal(t, true, p1.Evaluate(path1, nil)) + assert.Equal(t, true, p2.Evaluate(path1, nil)) + assert.Equal(t, true, p3.Evaluate(path1, nil)) + assert.Equal(t, false, p4.Evaluate(path1, nil)) + assert.Equal(t, true, p5.Evaluate(path1, nil)) + assert.Equal(t, false, p6.Evaluate(path1, nil)) + assert.Equal(t, true, p6.Evaluate(path2, nil)) + assert.Equal(t, true, p7.Evaluate(path1, nil)) + assert.Equal(t, true, p8.Evaluate(path2, nil)) +} + +func TestMultipleAsPathConditionEvaluate(t *testing.T) { + + // setup + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam1 := []bgp.AsPathParamInterface{ + bgp.NewAsPathParam(2, []uint16{65001, 65000, 54000, 65004, 65005}), + } + aspath := bgp.NewPathAttributeAsPath(aspathParam1) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate)) + path1 := ProcessMessage(updateMsg1, peer, time.Now())[0] + + // create match condition + asPathSet1 := config.AsPathSet{ + AsPathSetName: "asset1", + AsPathList: []string{"^65001_65000"}, + } + + asPathSet2 := config.AsPathSet{ + AsPathSetName: "asset2", + AsPathList: []string{"65004_65005$"}, + } + + asPathSet3 := config.AsPathSet{ + AsPathSetName: "asset3", + AsPathList: []string{"65001_65000_54000"}, + } + + asPathSet4 := config.AsPathSet{ + AsPathSetName: "asset4", + AsPathList: []string{"54000_65004_65005"}, + } + + asPathSet5 := config.AsPathSet{ + AsPathSetName: "asset5", + AsPathList: []string{"^65001 65000 54000 65004 65005$"}, + } + + asPathSet6 := config.AsPathSet{ + AsPathSetName: "asset6", + AsPathList: []string{".*_[0-9]+_65005"}, + } + + asPathSet7 := config.AsPathSet{ + AsPathSetName: "asset7", + AsPathList: []string{".*_5[0-9]+_[0-9]+"}, + } + + asPathSet8 := config.AsPathSet{ + AsPathSetName: "asset8", + AsPathList: []string{"6[0-9]+_6[0-9]+_5[0-9]+"}, + } + + asPathSet9 := config.AsPathSet{ + AsPathSetName: "asset9", + AsPathList: []string{"6[0-9]+__6[0-9]+"}, + } + + m := make(map[string]DefinedSet) + for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3, + asPathSet4, asPathSet5, asPathSet6, asPathSet7, asPathSet8, asPathSet9} { + a, _ := NewAsPathSet(s) + m[s.AsPathSetName] = a + } + + createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition { + matchSet := config.MatchAsPathSet{} + matchSet.AsPathSet = name + matchSet.MatchSetOptions = option + p, _ := NewAsPathCondition(matchSet) + if v, ok := m[name]; ok { + p.set = v.(*AsPathSet) + } + return p + } + + p1 := createAspathC("asset1", config.MATCH_SET_OPTIONS_TYPE_ANY) + p2 := createAspathC("asset2", config.MATCH_SET_OPTIONS_TYPE_ANY) + p3 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ANY) + p4 := createAspathC("asset4", config.MATCH_SET_OPTIONS_TYPE_ANY) + p5 := createAspathC("asset5", config.MATCH_SET_OPTIONS_TYPE_ANY) + p6 := createAspathC("asset6", config.MATCH_SET_OPTIONS_TYPE_ANY) + p7 := createAspathC("asset7", config.MATCH_SET_OPTIONS_TYPE_ANY) + p8 := createAspathC("asset8", config.MATCH_SET_OPTIONS_TYPE_ANY) + p9 := createAspathC("asset9", config.MATCH_SET_OPTIONS_TYPE_ANY) + + // test + assert.Equal(t, true, p1.Evaluate(path1, nil)) + assert.Equal(t, true, p2.Evaluate(path1, nil)) + assert.Equal(t, true, p3.Evaluate(path1, nil)) + assert.Equal(t, true, p4.Evaluate(path1, nil)) + assert.Equal(t, true, p5.Evaluate(path1, nil)) + assert.Equal(t, true, p6.Evaluate(path1, nil)) + assert.Equal(t, true, p7.Evaluate(path1, nil)) + assert.Equal(t, true, p8.Evaluate(path1, nil)) + assert.Equal(t, false, p9.Evaluate(path1, nil)) +} + +func TestAsPathCondition(t *testing.T) { + type astest struct { + path *Path + result bool + } + + makeTest := func(asPathAttrType uint8, ases []uint32, result bool) astest { + aspathParam := []bgp.AsPathParamInterface{ + bgp.NewAs4PathParam(asPathAttrType, ases), + } + pathAttributes := []bgp.PathAttributeInterface{bgp.NewPathAttributeAsPath(aspathParam)} + p := NewPath(nil, nil, false, pathAttributes, time.Time{}, false) + return astest{ + path: p, + result: result, + } + } + + tests := make(map[string][]astest) + + tests["^(100_)+(200_)+$"] = []astest{ + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{100, 200}, true), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{100, 100, 200}, true), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{100, 100, 200, 200}, true), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{100, 100, 200, 200, 300}, false), + } + + aslen255 := func() []uint32 { + r := make([]uint32, 255) + for i := 0; i < 255; i++ { + r[i] = 1 + } + return r + }() + tests["^([0-9]+_){0,255}$"] = []astest{ + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, aslen255, true), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, append(aslen255, 1), false), + } + + tests["(_7521)$"] = []astest{ + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{7521}, true), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{1000, 7521}, true), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{7521, 1000}, false), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{1000, 7521, 100}, false), + } + + tests["^65001( |_.*_)65535$"] = []astest{ + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65535}, true), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65001, 65535}, true), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65002, 65003, 65535}, true), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65534}, false), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65002, 65535}, false), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65002, 65001, 65535}, false), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65535, 65002}, false), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{650019, 65535}, false), + makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 165535}, false), + } + + for k, v := range tests { + s, _ := NewAsPathSet(config.AsPathSet{ + AsPathSetName: k, + AsPathList: []string{k}, + }) + c, _ := NewAsPathCondition(config.MatchAsPathSet{ + AsPathSet: k, + MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY, + }) + c.set = s + for _, a := range v { + result := c.Evaluate(a.path, nil) + if a.result != result { + log.WithFields(log.Fields{ + "EXP": k, + "ASSTR": a.path.GetAsString(), + "Expected": a.result, + "Result": result, + }).Fatal("failed") + } + } + } +} + +func TestAsPathConditionWithOtherCondition(t *testing.T) { + + // setup + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{ + bgp.NewAsPathParam(1, []uint16{65001, 65000, 65004, 65005}), + bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 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.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate)) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + asPathSet := config.AsPathSet{ + AsPathSetName: "asset1", + AsPathList: []string{"65005$"}, + } + + ps := createPrefixSet("ps1", "10.10.1.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + ds.BgpDefinedSets.AsPathSets = []config.AsPathSet{asPathSet} + + s := createStatement("statement1", "ps1", "ns1", false) + s.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = "asset1" + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_REJECT, pType) + assert.Equal(t, newPath, path) + +} + +func TestAs4PathConditionEvaluate(t *testing.T) { + + // setup + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam1 := []bgp.AsPathParamInterface{ + bgp.NewAs4PathParam(2, []uint32{ + createAs4Value("65001.1"), + createAs4Value("65000.1"), + createAs4Value("65010.1"), + createAs4Value("65004.1"), + createAs4Value("65005.1"), + })} + + aspath := bgp.NewPathAttributeAsPath(aspathParam1) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate)) + path1 := ProcessMessage(updateMsg1, peer, time.Now())[0] + + aspathParam2 := []bgp.AsPathParamInterface{ + bgp.NewAs4PathParam(2, []uint32{ + createAs4Value("65010.1"), + }), + } + aspath2 := bgp.NewPathAttributeAsPath(aspathParam2) + pathAttributes = []bgp.PathAttributeInterface{origin, aspath2, nexthop, med} + updateMsg2 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg2.Body.(*bgp.BGPUpdate)) + path2 := ProcessMessage(updateMsg2, peer, time.Now())[0] + + // create match condition + asPathSet1 := config.AsPathSet{ + AsPathSetName: "asset1", + AsPathList: []string{fmt.Sprintf("^%d", createAs4Value("65001.1"))}, + } + + asPathSet2 := config.AsPathSet{ + AsPathSetName: "asset2", + AsPathList: []string{fmt.Sprintf("%d$", createAs4Value("65005.1"))}, + } + + asPathSet3 := config.AsPathSet{ + AsPathSetName: "asset3", + AsPathList: []string{ + fmt.Sprintf("%d", createAs4Value("65004.1")), + fmt.Sprintf("%d$", createAs4Value("65005.1")), + }, + } + + asPathSet4 := config.AsPathSet{ + AsPathSetName: "asset4", + AsPathList: []string{ + fmt.Sprintf("%d$", createAs4Value("65000.1")), + }, + } + + asPathSet5 := config.AsPathSet{ + AsPathSetName: "asset5", + AsPathList: []string{ + fmt.Sprintf("%d", createAs4Value("65010.1")), + }, + } + + asPathSet6 := config.AsPathSet{ + AsPathSetName: "asset6", + AsPathList: []string{ + fmt.Sprintf("%d$", createAs4Value("65010.1")), + }, + } + + m := make(map[string]DefinedSet) + for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3, + asPathSet4, asPathSet5, asPathSet6} { + a, _ := NewAsPathSet(s) + m[s.AsPathSetName] = a + } + + createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition { + matchSet := config.MatchAsPathSet{} + matchSet.AsPathSet = name + matchSet.MatchSetOptions = option + p, _ := NewAsPathCondition(matchSet) + if v, ok := m[name]; ok { + p.set = v.(*AsPathSet) + } + return p + } + + p1 := createAspathC("asset1", config.MATCH_SET_OPTIONS_TYPE_ANY) + p2 := createAspathC("asset2", config.MATCH_SET_OPTIONS_TYPE_ANY) + p3 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ANY) + p4 := createAspathC("asset4", config.MATCH_SET_OPTIONS_TYPE_ANY) + p5 := createAspathC("asset5", config.MATCH_SET_OPTIONS_TYPE_ANY) + p6 := createAspathC("asset6", config.MATCH_SET_OPTIONS_TYPE_ANY) + + p7 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ALL) + p8 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_INVERT) + + // test + assert.Equal(t, true, p1.Evaluate(path1, nil)) + assert.Equal(t, true, p2.Evaluate(path1, nil)) + assert.Equal(t, true, p3.Evaluate(path1, nil)) + assert.Equal(t, false, p4.Evaluate(path1, nil)) + assert.Equal(t, true, p5.Evaluate(path1, nil)) + assert.Equal(t, false, p6.Evaluate(path1, nil)) + assert.Equal(t, true, p6.Evaluate(path2, nil)) + + assert.Equal(t, true, p7.Evaluate(path1, nil)) + assert.Equal(t, true, p8.Evaluate(path2, nil)) +} + +func TestMultipleAs4PathConditionEvaluate(t *testing.T) { + + // setup + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam1 := []bgp.AsPathParamInterface{ + bgp.NewAs4PathParam(2, []uint32{ + createAs4Value("65001.1"), + createAs4Value("65000.1"), + createAs4Value("54000.1"), + createAs4Value("65004.1"), + createAs4Value("65005.1"), + }), + } + + aspath := bgp.NewPathAttributeAsPath(aspathParam1) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate)) + path1 := ProcessMessage(updateMsg1, peer, time.Now())[0] + + // create match condition + asPathSet1 := config.AsPathSet{ + AsPathSetName: "asset1", + AsPathList: []string{ + fmt.Sprintf("^%d_%d", createAs4Value("65001.1"), createAs4Value("65000.1")), + }, + } + + asPathSet2 := config.AsPathSet{ + AsPathSetName: "asset2", + AsPathList: []string{ + fmt.Sprintf("%d_%d$", createAs4Value("65004.1"), createAs4Value("65005.1")), + }, + } + + asPathSet3 := config.AsPathSet{ + AsPathSetName: "asset3", + AsPathList: []string{ + fmt.Sprintf("%d_%d_%d", createAs4Value("65001.1"), createAs4Value("65000.1"), createAs4Value("54000.1")), + }, + } + + asPathSet4 := config.AsPathSet{ + AsPathSetName: "asset4", + AsPathList: []string{ + fmt.Sprintf("%d_%d_%d", createAs4Value("54000.1"), createAs4Value("65004.1"), createAs4Value("65005.1")), + }, + } + + asPathSet5 := config.AsPathSet{ + AsPathSetName: "asset5", + AsPathList: []string{ + fmt.Sprintf("^%d %d %d %d %d$", createAs4Value("65001.1"), createAs4Value("65000.1"), createAs4Value("54000.1"), createAs4Value("65004.1"), createAs4Value("65005.1")), + }, + } + + asPathSet6 := config.AsPathSet{ + AsPathSetName: "asset6", + AsPathList: []string{ + fmt.Sprintf(".*_[0-9]+_%d", createAs4Value("65005.1")), + }, + } + + asPathSet7 := config.AsPathSet{ + AsPathSetName: "asset7", + AsPathList: []string{".*_3[0-9]+_[0-9]+"}, + } + + asPathSet8 := config.AsPathSet{ + AsPathSetName: "asset8", + AsPathList: []string{"4[0-9]+_4[0-9]+_3[0-9]+"}, + } + + asPathSet9 := config.AsPathSet{ + AsPathSetName: "asset9", + AsPathList: []string{"4[0-9]+__4[0-9]+"}, + } + + m := make(map[string]DefinedSet) + for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3, + asPathSet4, asPathSet5, asPathSet6, asPathSet7, asPathSet8, asPathSet9} { + a, _ := NewAsPathSet(s) + m[s.AsPathSetName] = a + } + + createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition { + matchSet := config.MatchAsPathSet{} + matchSet.AsPathSet = name + matchSet.MatchSetOptions = option + p, _ := NewAsPathCondition(matchSet) + if v, ok := m[name]; ok { + p.set = v.(*AsPathSet) + } + return p + } + + p1 := createAspathC("asset1", config.MATCH_SET_OPTIONS_TYPE_ANY) + p2 := createAspathC("asset2", config.MATCH_SET_OPTIONS_TYPE_ANY) + p3 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ANY) + p4 := createAspathC("asset4", config.MATCH_SET_OPTIONS_TYPE_ANY) + p5 := createAspathC("asset5", config.MATCH_SET_OPTIONS_TYPE_ANY) + p6 := createAspathC("asset6", config.MATCH_SET_OPTIONS_TYPE_ANY) + p7 := createAspathC("asset7", config.MATCH_SET_OPTIONS_TYPE_ANY) + p8 := createAspathC("asset8", config.MATCH_SET_OPTIONS_TYPE_ANY) + p9 := createAspathC("asset9", config.MATCH_SET_OPTIONS_TYPE_ANY) + + // test + assert.Equal(t, true, p1.Evaluate(path1, nil)) + assert.Equal(t, true, p2.Evaluate(path1, nil)) + assert.Equal(t, true, p3.Evaluate(path1, nil)) + assert.Equal(t, true, p4.Evaluate(path1, nil)) + assert.Equal(t, true, p5.Evaluate(path1, nil)) + assert.Equal(t, true, p6.Evaluate(path1, nil)) + assert.Equal(t, true, p7.Evaluate(path1, nil)) + assert.Equal(t, true, p8.Evaluate(path1, nil)) + assert.Equal(t, false, p9.Evaluate(path1, nil)) +} + +func TestAs4PathConditionWithOtherCondition(t *testing.T) { + + // setup + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{ + bgp.NewAs4PathParam(1, []uint32{ + createAs4Value("65001.1"), + createAs4Value("65000.1"), + createAs4Value("65004.1"), + createAs4Value("65005.1"), + }), + bgp.NewAs4PathParam(2, []uint32{ + createAs4Value("65001.1"), + createAs4Value("65000.1"), + createAs4Value("65004.1"), + createAs4Value("65004.1"), + createAs4Value("65005.1"), + }), + } + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate)) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + asPathSet := config.AsPathSet{ + AsPathSetName: "asset1", + AsPathList: []string{fmt.Sprintf("%d$", createAs4Value("65005.1"))}, + } + + ps := createPrefixSet("ps1", "10.10.1.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + ds.BgpDefinedSets.AsPathSets = []config.AsPathSet{asPathSet} + + s := createStatement("statement1", "ps1", "ns1", false) + s.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = "asset1" + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + r.reload(pl) + p, _ := NewPolicy(pl.PolicyDefinitions[0]) + addPolicy(r, p) + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_REJECT, pType) + assert.Equal(t, newPath, path) + +} + +func TestAs4PathConditionEvaluateMixedWith2byteAS(t *testing.T) { + + // setup + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam1 := []bgp.AsPathParamInterface{ + bgp.NewAs4PathParam(2, []uint32{ + createAs4Value("65001.1"), + createAs4Value("65000.1"), + createAs4Value("54000.1"), + 100, + 5000, + createAs4Value("65004.1"), + createAs4Value("65005.1"), + 4000, + }), + } + + aspath := bgp.NewPathAttributeAsPath(aspathParam1) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate)) + path1 := ProcessMessage(updateMsg1, peer, time.Now())[0] + + // create match condition + asPathSet1 := config.AsPathSet{ + AsPathSetName: "asset1", + AsPathList: []string{fmt.Sprintf("^%d", createAs4Value("65001.1"))}, + } + + asPathSet2 := config.AsPathSet{ + AsPathSetName: "asset2", + AsPathList: []string{"4000$"}, + } + + asPathSet3 := config.AsPathSet{ + AsPathSetName: "asset3", + AsPathList: []string{fmt.Sprintf("%d", createAs4Value("65004.1")), "4000$"}, + } + + asPathSet4 := config.AsPathSet{ + AsPathSetName: "asset4", + AsPathList: []string{fmt.Sprintf("%d_%d_%d", createAs4Value("54000.1"), 100, 5000)}, + } + + asPathSet5 := config.AsPathSet{ + AsPathSetName: "asset5", + AsPathList: []string{".*_[0-9]+_100"}, + } + + asPathSet6 := config.AsPathSet{ + AsPathSetName: "asset6", + AsPathList: []string{".*_3[0-9]+_[0]+"}, + } + + asPathSet7 := config.AsPathSet{ + AsPathSetName: "asset7", + AsPathList: []string{".*_3[0-9]+_[1]+"}, + } + + m := make(map[string]DefinedSet) + for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3, + asPathSet4, asPathSet5, asPathSet6, asPathSet7} { + a, _ := NewAsPathSet(s) + m[s.AsPathSetName] = a + } + + createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition { + matchSet := config.MatchAsPathSet{} + matchSet.AsPathSet = name + matchSet.MatchSetOptions = option + p, _ := NewAsPathCondition(matchSet) + if v, ok := m[name]; ok { + p.set = v.(*AsPathSet) + } + return p + } + + p1 := createAspathC("asset1", config.MATCH_SET_OPTIONS_TYPE_ANY) + p2 := createAspathC("asset2", config.MATCH_SET_OPTIONS_TYPE_ANY) + p3 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ALL) + p4 := createAspathC("asset4", config.MATCH_SET_OPTIONS_TYPE_ANY) + p5 := createAspathC("asset5", config.MATCH_SET_OPTIONS_TYPE_ANY) + p6 := createAspathC("asset6", config.MATCH_SET_OPTIONS_TYPE_ANY) + p7 := createAspathC("asset7", config.MATCH_SET_OPTIONS_TYPE_ANY) + + // test + assert.Equal(t, true, p1.Evaluate(path1, nil)) + assert.Equal(t, true, p2.Evaluate(path1, nil)) + assert.Equal(t, true, p3.Evaluate(path1, nil)) + assert.Equal(t, true, p4.Evaluate(path1, nil)) + assert.Equal(t, true, p5.Evaluate(path1, nil)) + assert.Equal(t, false, p6.Evaluate(path1, nil)) + assert.Equal(t, true, p7.Evaluate(path1, nil)) + +} + +func TestCommunityConditionEvaluate(t *testing.T) { + + // setup + // create path + peer := &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) + communities := bgp.NewPathAttributeCommunities([]uint32{ + stringToCommunityValue("65001:100"), + stringToCommunityValue("65001:200"), + stringToCommunityValue("65001:300"), + stringToCommunityValue("65001:400"), + 0x00000000, + 0xFFFFFF01, + 0xFFFFFF02, + 0xFFFFFF03}) + + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate)) + path1 := ProcessMessage(updateMsg1, peer, time.Now())[0] + + communities2 := bgp.NewPathAttributeCommunities([]uint32{ + stringToCommunityValue("65001:100"), + stringToCommunityValue("65001:200"), + stringToCommunityValue("65001:300"), + stringToCommunityValue("65001:400")}) + + pathAttributes2 := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities2} + updateMsg2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri) + UpdatePathAttrs4ByteAs(updateMsg2.Body.(*bgp.BGPUpdate)) + path2 := ProcessMessage(updateMsg2, peer, time.Now())[0] + + // create match condition + comSet1 := config.CommunitySet{ + CommunitySetName: "comset1", + CommunityList: []string{"65001:10", "65001:50", "65001:100"}, + } + + comSet2 := config.CommunitySet{ + CommunitySetName: "comset2", + CommunityList: []string{"65001:200"}, + } + + comSet3 := config.CommunitySet{ + CommunitySetName: "comset3", + CommunityList: []string{"4259905936"}, + } + + comSet4 := config.CommunitySet{ + CommunitySetName: "comset4", + CommunityList: []string{"^[0-9]*:300$"}, + } + + comSet5 := config.CommunitySet{ + CommunitySetName: "comset5", + CommunityList: []string{"INTERNET"}, + } + + comSet6 := config.CommunitySet{ + CommunitySetName: "comset6", + CommunityList: []string{"NO_EXPORT"}, + } + + comSet7 := config.CommunitySet{ + CommunitySetName: "comset7", + CommunityList: []string{"NO_ADVERTISE"}, + } + + comSet8 := config.CommunitySet{ + CommunitySetName: "comset8", + CommunityList: []string{"NO_EXPORT_SUBCONFED"}, + } + + comSet9 := config.CommunitySet{ + CommunitySetName: "comset9", + CommunityList: []string{ + "65001:\\d+", + "\\d+:\\d00", + }, + } + + comSet10 := config.CommunitySet{ + CommunitySetName: "comset10", + CommunityList: []string{ + "65001:1", + "65001:2", + "65001:3", + }, + } + + m := make(map[string]DefinedSet) + + for _, c := range []config.CommunitySet{comSet1, comSet2, comSet3, + comSet4, comSet5, comSet6, comSet7, comSet8, comSet9, comSet10} { + s, _ := NewCommunitySet(c) + m[c.CommunitySetName] = s + } + + createCommunityC := func(name string, option config.MatchSetOptionsType) *CommunityCondition { + matchSet := config.MatchCommunitySet{} + matchSet.CommunitySet = name + matchSet.MatchSetOptions = option + c, _ := NewCommunityCondition(matchSet) + if v, ok := m[name]; ok { + c.set = v.(*CommunitySet) + } + return c + } + + // ANY case + p1 := createCommunityC("comset1", config.MATCH_SET_OPTIONS_TYPE_ANY) + p2 := createCommunityC("comset2", config.MATCH_SET_OPTIONS_TYPE_ANY) + p3 := createCommunityC("comset3", config.MATCH_SET_OPTIONS_TYPE_ANY) + p4 := createCommunityC("comset4", config.MATCH_SET_OPTIONS_TYPE_ANY) + p5 := createCommunityC("comset5", config.MATCH_SET_OPTIONS_TYPE_ANY) + p6 := createCommunityC("comset6", config.MATCH_SET_OPTIONS_TYPE_ANY) + p7 := createCommunityC("comset7", config.MATCH_SET_OPTIONS_TYPE_ANY) + p8 := createCommunityC("comset8", config.MATCH_SET_OPTIONS_TYPE_ANY) + + // ALL case + p9 := createCommunityC("comset9", config.MATCH_SET_OPTIONS_TYPE_ALL) + + // INVERT case + p10 := createCommunityC("comset10", config.MATCH_SET_OPTIONS_TYPE_INVERT) + + // test + assert.Equal(t, true, p1.Evaluate(path1, nil)) + assert.Equal(t, true, p2.Evaluate(path1, nil)) + assert.Equal(t, true, p3.Evaluate(path1, nil)) + assert.Equal(t, true, p4.Evaluate(path1, nil)) + assert.Equal(t, true, p5.Evaluate(path1, nil)) + assert.Equal(t, true, p6.Evaluate(path1, nil)) + assert.Equal(t, true, p7.Evaluate(path1, nil)) + assert.Equal(t, true, p8.Evaluate(path1, nil)) + assert.Equal(t, true, p9.Evaluate(path2, nil)) + assert.Equal(t, true, p10.Evaluate(path1, nil)) + +} + +func TestCommunityConditionEvaluateWithOtherCondition(t *testing.T) { + + // setup + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{ + bgp.NewAsPathParam(1, []uint16{65001, 65000, 65004, 65005}), + bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 65004, 65005}), + } + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + communities := bgp.NewPathAttributeCommunities([]uint32{ + stringToCommunityValue("65001:100"), + stringToCommunityValue("65001:200"), + stringToCommunityValue("65001:300"), + stringToCommunityValue("65001:400"), + 0x00000000, + 0xFFFFFF01, + 0xFFFFFF02, + 0xFFFFFF03}) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate)) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + asPathSet := config.AsPathSet{ + AsPathSetName: "asset1", + AsPathList: []string{"65005$"}, + } + + comSet1 := config.CommunitySet{ + CommunitySetName: "comset1", + CommunityList: []string{"65001:100", "65001:200", "65001:300"}, + } + + comSet2 := config.CommunitySet{ + CommunitySetName: "comset2", + CommunityList: []string{"65050:\\d+"}, + } + + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + ds.BgpDefinedSets.AsPathSets = []config.AsPathSet{asPathSet} + ds.BgpDefinedSets.CommunitySets = []config.CommunitySet{comSet1, comSet2} + + s1 := createStatement("statement1", "ps1", "ns1", false) + s1.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = "asset1" + s1.Conditions.BgpConditions.MatchCommunitySet.CommunitySet = "comset1" + + s2 := createStatement("statement2", "ps1", "ns1", false) + s2.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = "asset1" + s2.Conditions.BgpConditions.MatchCommunitySet.CommunitySet = "comset2" + + pd1 := createPolicyDefinition("pd1", s1) + pd2 := createPolicyDefinition("pd2", s2) + pl := createRoutingPolicy(ds, pd1, pd2) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_REJECT, pType) + assert.Equal(t, newPath, path) + + p = r.policyMap["pd2"] + pType, newPath = p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_NONE, pType) + assert.Equal(t, newPath, path) + +} + +func TestPolicyMatchAndAddCommunities(t *testing.T) { + + // create path + peer := &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(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + community := "65000:100" + + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetCommunity = createSetCommunity("ADD", community) + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(t, nil, newPath) + assert.Equal(t, []uint32{stringToCommunityValue(community)}, newPath.GetCommunities()) +} + +func TestPolicyMatchAndReplaceCommunities(t *testing.T) { + + // create path + peer := &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(0) + communities := bgp.NewPathAttributeCommunities([]uint32{ + stringToCommunityValue("65001:200"), + }) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + community := "65000:100" + + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetCommunity = createSetCommunity("REPLACE", community) + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(t, nil, newPath) + assert.Equal(t, []uint32{stringToCommunityValue(community)}, newPath.GetCommunities()) +} + +func TestPolicyMatchAndRemoveCommunities(t *testing.T) { + + // create path + community1 := "65000:100" + community2 := "65000:200" + peer := &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(0) + communities := bgp.NewPathAttributeCommunities([]uint32{ + stringToCommunityValue(community1), + stringToCommunityValue(community2), + }) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetCommunity = createSetCommunity("REMOVE", community1) + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(t, nil, newPath) + assert.Equal(t, []uint32{stringToCommunityValue(community2)}, newPath.GetCommunities()) +} + +func TestPolicyMatchAndRemoveCommunitiesRegexp(t *testing.T) { + + // create path + community1 := "65000:100" + community2 := "65000:200" + community3 := "65100:100" + peer := &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(0) + communities := bgp.NewPathAttributeCommunities([]uint32{ + stringToCommunityValue(community1), + stringToCommunityValue(community2), + stringToCommunityValue(community3), + }) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetCommunity = createSetCommunity("REMOVE", ".*:100") + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(t, nil, newPath) + assert.Equal(t, []uint32{stringToCommunityValue(community2)}, newPath.GetCommunities()) +} + +func TestPolicyMatchAndRemoveCommunitiesRegexp2(t *testing.T) { + + // create path + community1 := "0:1" + community2 := "10:1" + community3 := "45686:2" + peer := &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(0) + communities := bgp.NewPathAttributeCommunities([]uint32{ + stringToCommunityValue(community1), + stringToCommunityValue(community2), + stringToCommunityValue(community3), + }) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetCommunity = createSetCommunity("REMOVE", "^(0|45686):[0-9]+") + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(t, nil, newPath) + assert.Equal(t, []uint32{stringToCommunityValue(community2)}, newPath.GetCommunities()) +} + +func TestPolicyMatchAndClearCommunities(t *testing.T) { + + // create path + community1 := "65000:100" + community2 := "65000:200" + peer := &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(0) + communities := bgp.NewPathAttributeCommunities([]uint32{ + stringToCommunityValue(community1), + stringToCommunityValue(community2), + }) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + s := createStatement("statement1", "ps1", "ns1", true) + // action NULL is obsolate + s.Actions.BgpActions.SetCommunity.Options = "REPLACE" + s.Actions.BgpActions.SetCommunity.SetCommunityMethod.CommunitiesList = nil + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(t, nil, newPath) + //assert.Equal(t, []uint32{}, newPath.GetCommunities()) +} + +func TestExtCommunityConditionEvaluate(t *testing.T) { + + // setup + // create path + peer := &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.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate)) + path1 := ProcessMessage(updateMsg1, peer, time.Now())[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", + ExtCommunityList: []string{"RT:65001:200"}, + } + ecomSet2 := config.ExtCommunitySet{ + ExtCommunitySetName: "ecomSet2", + ExtCommunityList: []string{"RT:10.0.0.1:300"}, + } + ecomSet3 := config.ExtCommunitySet{ + ExtCommunitySetName: "ecomSet3", + ExtCommunityList: []string{fmt.Sprintf("RT:%s:200", convUintStr(65030000))}, + } + ecomSet4 := config.ExtCommunitySet{ + ExtCommunitySetName: "ecomSet4", + ExtCommunityList: []string{"RT:65002:200"}, + } + ecomSet5 := config.ExtCommunitySet{ + ExtCommunitySetName: "ecomSet5", + ExtCommunityList: []string{"RT:10.0.0.2:300"}, + } + ecomSet6 := config.ExtCommunitySet{ + ExtCommunitySetName: "ecomSet6", + ExtCommunityList: []string{fmt.Sprintf("RT:%s:200", convUintStr(65030001))}, + } + ecomSet7 := config.ExtCommunitySet{ + ExtCommunitySetName: "ecomSet7", + ExtCommunityList: []string{"SoO:65010:300"}, + } + ecomSet8 := config.ExtCommunitySet{ + ExtCommunitySetName: "ecomSet8", + ExtCommunityList: []string{"SoO:10.0.10.10:[0-9]+"}, + } + ecomSet9 := config.ExtCommunitySet{ + ExtCommunitySetName: "ecomSet9", + ExtCommunityList: []string{"RT:[0-9]+:[0-9]+"}, + } + ecomSet10 := config.ExtCommunitySet{ + ExtCommunitySetName: "ecomSet10", + ExtCommunityList: []string{"RT:.+:\\d00", "SoO:.+:\\d00"}, + } + + ecomSet11 := config.ExtCommunitySet{ + ExtCommunitySetName: "ecomSet11", + ExtCommunityList: []string{"RT:65001:2", "SoO:11.0.10.10:[0-9]+"}, + } + + m := make(map[string]DefinedSet) + for _, c := range []config.ExtCommunitySet{ecomSet1, ecomSet2, ecomSet3, ecomSet4, ecomSet5, ecomSet6, ecomSet7, + ecomSet8, ecomSet9, ecomSet10, ecomSet11} { + s, _ := NewExtCommunitySet(c) + m[s.Name()] = s + } + + createExtCommunityC := func(name string, option config.MatchSetOptionsType) *ExtCommunityCondition { + matchSet := config.MatchExtCommunitySet{} + matchSet.ExtCommunitySet = name + matchSet.MatchSetOptions = option + c, _ := NewExtCommunityCondition(matchSet) + if v, ok := m[name]; ok { + c.set = v.(*ExtCommunitySet) + } + + return c + } + + p1 := createExtCommunityC("ecomSet1", config.MATCH_SET_OPTIONS_TYPE_ANY) + p2 := createExtCommunityC("ecomSet2", config.MATCH_SET_OPTIONS_TYPE_ANY) + p3 := createExtCommunityC("ecomSet3", config.MATCH_SET_OPTIONS_TYPE_ANY) + p4 := createExtCommunityC("ecomSet4", config.MATCH_SET_OPTIONS_TYPE_ANY) + p5 := createExtCommunityC("ecomSet5", config.MATCH_SET_OPTIONS_TYPE_ANY) + p6 := createExtCommunityC("ecomSet6", config.MATCH_SET_OPTIONS_TYPE_ANY) + p7 := createExtCommunityC("ecomSet7", config.MATCH_SET_OPTIONS_TYPE_ANY) + p8 := createExtCommunityC("ecomSet8", config.MATCH_SET_OPTIONS_TYPE_ANY) + p9 := createExtCommunityC("ecomSet9", config.MATCH_SET_OPTIONS_TYPE_ANY) + + // ALL case + p10 := createExtCommunityC("ecomSet10", config.MATCH_SET_OPTIONS_TYPE_ALL) + + // INVERT case + p11 := createExtCommunityC("ecomSet11", config.MATCH_SET_OPTIONS_TYPE_INVERT) + + // test + assert.Equal(t, true, p1.Evaluate(path1, nil)) + assert.Equal(t, true, p2.Evaluate(path1, nil)) + assert.Equal(t, true, p3.Evaluate(path1, nil)) + assert.Equal(t, false, p4.Evaluate(path1, nil)) + assert.Equal(t, false, p5.Evaluate(path1, nil)) + assert.Equal(t, false, p6.Evaluate(path1, nil)) + assert.Equal(t, true, p7.Evaluate(path1, nil)) + assert.Equal(t, true, p8.Evaluate(path1, nil)) + assert.Equal(t, true, p9.Evaluate(path1, nil)) + assert.Equal(t, true, p10.Evaluate(path1, nil)) + assert.Equal(t, true, p11.Evaluate(path1, nil)) + +} + +func TestExtCommunityConditionEvaluateWithOtherCondition(t *testing.T) { + + // setup + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.2.1.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{ + bgp.NewAsPathParam(1, []uint16{65001, 65000, 65004, 65005}), + bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 65004, 65005}), + } + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.2.1.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.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate)) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + asPathSet := config.AsPathSet{ + AsPathSetName: "asset1", + AsPathList: []string{"65005$"}, + } + + ecomSet1 := config.ExtCommunitySet{ + ExtCommunitySetName: "ecomSet1", + ExtCommunityList: []string{"RT:65001:201"}, + } + ecomSet2 := config.ExtCommunitySet{ + ExtCommunitySetName: "ecomSet2", + ExtCommunityList: []string{"RT:[0-9]+:[0-9]+"}, + } + + ps := createPrefixSet("ps1", "10.10.1.0/16", "21..24") + ns := createNeighborSet("ns1", "10.2.1.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + ds.BgpDefinedSets.AsPathSets = []config.AsPathSet{asPathSet} + ds.BgpDefinedSets.ExtCommunitySets = []config.ExtCommunitySet{ecomSet1, ecomSet2} + + s1 := createStatement("statement1", "ps1", "ns1", false) + s1.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = "asset1" + s1.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet = "ecomSet1" + + s2 := createStatement("statement2", "ps1", "ns1", false) + s2.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = "asset1" + s2.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet = "ecomSet2" + + pd1 := createPolicyDefinition("pd1", s1) + pd2 := createPolicyDefinition("pd2", s2) + pl := createRoutingPolicy(ds, pd1, pd2) + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_NONE, pType) + assert.Equal(t, newPath, path) + + p = r.policyMap["pd2"] + pType, newPath = p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_REJECT, pType) + assert.Equal(t, newPath, path) + +} + +func TestPolicyMatchAndReplaceMed(t *testing.T) { + + // create path + peer := &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.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + m := "200" + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetMed = config.BgpSetMedType(m) + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(t, nil, newPath) + v, err := newPath.GetMed() + assert.Nil(t, err) + newMed := fmt.Sprintf("%d", v) + assert.Equal(t, m, newMed) +} + +func TestPolicyMatchAndAddingMed(t *testing.T) { + + // create path + peer := &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.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + m := "+200" + ma := "300" + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetMed = config.BgpSetMedType(m) + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(t, nil, newPath) + + v, err := newPath.GetMed() + assert.Nil(t, err) + newMed := fmt.Sprintf("%d", v) + assert.Equal(t, ma, newMed) +} + +func TestPolicyMatchAndAddingMedOverFlow(t *testing.T) { + + // create path + peer := &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.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + m := fmt.Sprintf("+%d", uint32(math.MaxUint32)) + ma := "1" + + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetMed = config.BgpSetMedType(m) + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(t, nil, newPath) + + v, err := newPath.GetMed() + assert.Nil(t, err) + newMed := fmt.Sprintf("%d", v) + assert.Equal(t, ma, newMed) +} + +func TestPolicyMatchAndSubtractMed(t *testing.T) { + + // create path + peer := &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.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + m := "-50" + ma := "50" + + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetMed = config.BgpSetMedType(m) + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(t, nil, newPath) + + v, err := newPath.GetMed() + assert.Nil(t, err) + newMed := fmt.Sprintf("%d", v) + assert.Equal(t, ma, newMed) +} + +func TestPolicyMatchAndSubtractMedUnderFlow(t *testing.T) { + + // create path + peer := &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.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + m := "-101" + ma := "100" + + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetMed = config.BgpSetMedType(m) + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(t, nil, newPath) + + v, err := newPath.GetMed() + assert.Nil(t, err) + newMed := fmt.Sprintf("%d", v) + assert.Equal(t, ma, newMed) +} + +func TestPolicyMatchWhenPathHaveNotMed(t *testing.T) { + + // create path + peer := &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.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + m := "-50" + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetMed = config.BgpSetMedType(m) + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + //test + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + p := r.policyMap["pd1"] + + pType, newPath := p.Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(t, nil, newPath) + + _, err = newPath.GetMed() + assert.NotNil(t, err) +} + +func TestPolicyAsPathPrepend(t *testing.T) { + + assert := assert.New(t) + + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001, 65000})} + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + + body := updateMsg.Body.(*bgp.BGPUpdate) + UpdatePathAttrs4ByteAs(body) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetAsPathPrepend.As = "65002" + s.Actions.BgpActions.SetAsPathPrepend.RepeatN = 10 + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + //test + r := NewRoutingPolicy() + r.reload(pl) + p := r.policyMap["pd1"] + + pType, newPath := p.Apply(path, nil) + assert.Equal(ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(nil, newPath) + assert.Equal([]uint32{65002, 65002, 65002, 65002, 65002, 65002, 65002, 65002, 65002, 65002, 65001, 65000}, newPath.GetAsSeqList()) +} + +func TestPolicyAsPathPrependLastAs(t *testing.T) { + + assert := assert.New(t) + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65002, 65001, 65000})} + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + + body := updateMsg.Body.(*bgp.BGPUpdate) + UpdatePathAttrs4ByteAs(body) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetAsPathPrepend.As = "last-as" + s.Actions.BgpActions.SetAsPathPrepend.RepeatN = 5 + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + //test + r := NewRoutingPolicy() + r.reload(pl) + p := r.policyMap["pd1"] + + pType, newPath := p.Apply(path, nil) + assert.Equal(ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(nil, newPath) + assert.Equal([]uint32{65002, 65002, 65002, 65002, 65002, 65002, 65001, 65000}, newPath.GetAsSeqList()) +} + +func TestPolicyAs4PathPrepend(t *testing.T) { + + assert := assert.New(t) + + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{ + bgp.NewAs4PathParam(2, []uint32{ + createAs4Value("65001.1"), + createAs4Value("65000.1"), + }), + } + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + + body := updateMsg.Body.(*bgp.BGPUpdate) + UpdatePathAttrs4ByteAs(body) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetAsPathPrepend.As = fmt.Sprintf("%d", createAs4Value("65002.1")) + s.Actions.BgpActions.SetAsPathPrepend.RepeatN = 10 + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + //test + r := NewRoutingPolicy() + r.reload(pl) + p, err := NewPolicy(pl.PolicyDefinitions[0]) + assert.Nil(err) + addPolicy(r, p) + + pType, newPath := p.Apply(path, nil) + assert.Equal(ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(nil, newPath) + asn := createAs4Value("65002.1") + assert.Equal([]uint32{ + asn, asn, asn, asn, asn, asn, asn, asn, asn, asn, + createAs4Value("65001.1"), + createAs4Value("65000.1"), + }, newPath.GetAsSeqList()) +} + +func TestPolicyAs4PathPrependLastAs(t *testing.T) { + + assert := assert.New(t) + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{ + bgp.NewAs4PathParam(2, []uint32{ + createAs4Value("65002.1"), + createAs4Value("65001.1"), + createAs4Value("65000.1"), + }), + } + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + + body := updateMsg.Body.(*bgp.BGPUpdate) + UpdatePathAttrs4ByteAs(body) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + + s := createStatement("statement1", "ps1", "ns1", true) + s.Actions.BgpActions.SetAsPathPrepend.As = "last-as" + s.Actions.BgpActions.SetAsPathPrepend.RepeatN = 5 + + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + //test + r := NewRoutingPolicy() + r.reload(pl) + p, _ := NewPolicy(pl.PolicyDefinitions[0]) + addPolicy(r, p) + + pType, newPath := p.Apply(path, nil) + assert.Equal(ROUTE_TYPE_ACCEPT, pType) + assert.NotEqual(nil, newPath) + asn := createAs4Value("65002.1") + assert.Equal([]uint32{ + asn, asn, asn, asn, asn, + createAs4Value("65002.1"), + createAs4Value("65001.1"), + createAs4Value("65000.1"), + }, newPath.GetAsSeqList()) +} + +func TestParseCommunityRegexp(t *testing.T) { + exp, err := ParseCommunityRegexp("65000:1") + assert.Equal(t, nil, err) + assert.Equal(t, true, exp.MatchString("65000:1")) + assert.Equal(t, false, exp.MatchString("65000:100")) +} + +func TestLocalPrefAction(t *testing.T) { + action, err := NewLocalPrefAction(10) + assert.Nil(t, err) + + nlri := bgp.NewIPAddrPrefix(24, "10.0.0.0") + + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{ + bgp.NewAs4PathParam(2, []uint32{ + createAs4Value("65002.1"), + createAs4Value("65001.1"), + createAs4Value("65000.1"), + }), + } + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + + attrs := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + + path := NewPath(nil, nlri, false, attrs, time.Now(), false) + p := action.Apply(path, nil) + assert.NotNil(t, p) + + attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF) + assert.NotNil(t, attr) + lp := attr.(*bgp.PathAttributeLocalPref) + assert.Equal(t, int(lp.Value), int(10)) +} + +func createStatement(name, psname, nsname string, accept bool) config.Statement { + c := config.Conditions{ + MatchPrefixSet: config.MatchPrefixSet{ + PrefixSet: psname, + }, + MatchNeighborSet: config.MatchNeighborSet{ + NeighborSet: nsname, + }, + } + rd := config.ROUTE_DISPOSITION_REJECT_ROUTE + if accept { + rd = config.ROUTE_DISPOSITION_ACCEPT_ROUTE + } + a := config.Actions{ + RouteDisposition: rd, + } + s := config.Statement{ + Name: name, + Conditions: c, + Actions: a, + } + return s +} + +func createSetCommunity(operation string, community ...string) config.SetCommunity { + + s := config.SetCommunity{ + SetCommunityMethod: config.SetCommunityMethod{ + CommunitiesList: community, + }, + Options: operation, + } + return s +} + +func stringToCommunityValue(comStr string) uint32 { + elem := strings.Split(comStr, ":") + asn, _ := strconv.ParseUint(elem[0], 10, 16) + val, _ := strconv.ParseUint(elem[1], 10, 16) + return uint32(asn<<16 | val) +} + +func createPolicyDefinition(defName string, stmt ...config.Statement) config.PolicyDefinition { + pd := config.PolicyDefinition{ + Name: defName, + Statements: []config.Statement(stmt), + } + return pd +} + +func createRoutingPolicy(ds config.DefinedSets, pd ...config.PolicyDefinition) config.RoutingPolicy { + pl := config.RoutingPolicy{ + DefinedSets: ds, + PolicyDefinitions: []config.PolicyDefinition(pd), + } + return pl +} + +func createPrefixSet(name string, prefix string, maskLength string) config.PrefixSet { + ps := config.PrefixSet{ + PrefixSetName: name, + PrefixList: []config.Prefix{ + config.Prefix{ + IpPrefix: prefix, + MasklengthRange: maskLength, + }}, + } + return ps +} + +func createNeighborSet(name string, addr string) config.NeighborSet { + ns := config.NeighborSet{ + NeighborSetName: name, + NeighborInfoList: []string{addr}, + } + return ns +} + +func createAs4Value(s string) uint32 { + v := strings.Split(s, ".") + upper, _ := strconv.ParseUint(v[0], 10, 16) + lower, _ := strconv.ParseUint(v[1], 10, 16) + return uint32(upper<<16 | lower) +} + +func TestPrefixSetOperation(t *testing.T) { + // tryp to create prefixset with multiple families + p1 := config.Prefix{ + IpPrefix: "0.0.0.0/0", + MasklengthRange: "0..7", + } + p2 := config.Prefix{ + IpPrefix: "0::/25", + MasklengthRange: "25..128", + } + _, err := NewPrefixSet(config.PrefixSet{ + PrefixSetName: "ps1", + PrefixList: []config.Prefix{p1, p2}, + }) + assert.NotNil(t, err) + m1, _ := NewPrefixSet(config.PrefixSet{ + PrefixSetName: "ps1", + PrefixList: []config.Prefix{p1}, + }) + m2, err := NewPrefixSet(config.PrefixSet{PrefixSetName: "ps2"}) + assert.Nil(t, err) + err = m1.Append(m2) + assert.Nil(t, err) + err = m2.Append(m1) + assert.Nil(t, err) + assert.Equal(t, bgp.RF_IPv4_UC, m2.family) + p3, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/24", MasklengthRange: ""}) + p4, _ := NewPrefix(config.Prefix{IpPrefix: "0::/25", MasklengthRange: ""}) + _, err = NewPrefixSetFromApiStruct("ps3", []*Prefix{p3, p4}) + assert.NotNil(t, err) +} + +func TestPrefixSetMatch(t *testing.T) { + p1 := config.Prefix{ + IpPrefix: "0.0.0.0/0", + MasklengthRange: "0..7", + } + p2 := config.Prefix{ + IpPrefix: "0.0.0.0/0", + MasklengthRange: "25..32", + } + ps, err := NewPrefixSet(config.PrefixSet{ + PrefixSetName: "ps1", + PrefixList: []config.Prefix{p1, p2}, + }) + assert.Nil(t, err) + m := &PrefixCondition{ + set: ps, + } + + path := NewPath(nil, bgp.NewIPAddrPrefix(6, "0.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false) + assert.True(t, m.Evaluate(path, nil)) + + path = NewPath(nil, bgp.NewIPAddrPrefix(10, "0.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false) + assert.False(t, m.Evaluate(path, nil)) + + path = NewPath(nil, bgp.NewIPAddrPrefix(25, "0.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false) + assert.True(t, m.Evaluate(path, nil)) + + path = NewPath(nil, bgp.NewIPAddrPrefix(30, "0.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false) + assert.True(t, m.Evaluate(path, nil)) + + p3 := config.Prefix{ + IpPrefix: "0.0.0.0/0", + MasklengthRange: "9..10", + } + ps2, err := NewPrefixSet(config.PrefixSet{ + PrefixSetName: "ps2", + PrefixList: []config.Prefix{p3}, + }) + assert.Nil(t, err) + err = ps.Append(ps2) + assert.Nil(t, err) + + path = NewPath(nil, bgp.NewIPAddrPrefix(10, "0.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false) + assert.True(t, m.Evaluate(path, nil)) + + ps3, err := NewPrefixSet(config.PrefixSet{ + PrefixSetName: "ps3", + PrefixList: []config.Prefix{p1}, + }) + assert.Nil(t, err) + err = ps.Remove(ps3) + assert.Nil(t, err) + + path = NewPath(nil, bgp.NewIPAddrPrefix(6, "0.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false) + assert.False(t, m.Evaluate(path, nil)) +} + +func TestPrefixSetMatchV4withV6Prefix(t *testing.T) { + p1 := config.Prefix{ + IpPrefix: "c000::/3", + MasklengthRange: "3..128", + } + ps, err := NewPrefixSet(config.PrefixSet{ + PrefixSetName: "ps1", + PrefixList: []config.Prefix{p1}, + }) + assert.Nil(t, err) + m := &PrefixCondition{ + set: ps, + } + + path := NewPath(nil, bgp.NewIPAddrPrefix(6, "192.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false) + assert.False(t, m.Evaluate(path, nil)) +} + +func TestLargeCommunityMatchAction(t *testing.T) { + coms := []*bgp.LargeCommunity{ + &bgp.LargeCommunity{ASN: 100, LocalData1: 100, LocalData2: 100}, + &bgp.LargeCommunity{ASN: 100, LocalData1: 200, LocalData2: 200}, + } + p := NewPath(nil, nil, false, []bgp.PathAttributeInterface{bgp.NewPathAttributeLargeCommunities(coms)}, time.Time{}, false) + + c := config.LargeCommunitySet{ + LargeCommunitySetName: "l0", + LargeCommunityList: []string{ + "100:100:100", + "100:300:100", + }, + } + + set, err := NewLargeCommunitySet(c) + assert.Equal(t, err, nil) + + m, err := NewLargeCommunityCondition(config.MatchLargeCommunitySet{ + LargeCommunitySet: "l0", + }) + assert.Equal(t, err, nil) + m.set = set + + assert.Equal(t, m.Evaluate(p, nil), true) + + a, err := NewLargeCommunityAction(config.SetLargeCommunity{ + SetLargeCommunityMethod: config.SetLargeCommunityMethod{ + CommunitiesList: []string{"100:100:100"}, + }, + Options: config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE, + }) + assert.Equal(t, err, nil) + p = a.Apply(p, nil) + + assert.Equal(t, m.Evaluate(p, nil), false) + + a, err = NewLargeCommunityAction(config.SetLargeCommunity{ + SetLargeCommunityMethod: config.SetLargeCommunityMethod{ + CommunitiesList: []string{ + "100:300:100", + "200:100:100", + }, + }, + Options: config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD, + }) + assert.Equal(t, err, nil) + p = a.Apply(p, nil) + + assert.Equal(t, m.Evaluate(p, nil), true) + + a, err = NewLargeCommunityAction(config.SetLargeCommunity{ + SetLargeCommunityMethod: config.SetLargeCommunityMethod{ + CommunitiesList: []string{"^100:"}, + }, + Options: config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE, + }) + assert.Equal(t, err, nil) + p = a.Apply(p, nil) + + assert.Equal(t, m.Evaluate(p, nil), false) + + c = config.LargeCommunitySet{ + LargeCommunitySetName: "l1", + LargeCommunityList: []string{ + "200:", + }, + } + + set, err = NewLargeCommunitySet(c) + assert.Equal(t, err, nil) + + m, err = NewLargeCommunityCondition(config.MatchLargeCommunitySet{ + LargeCommunitySet: "l1", + }) + assert.Equal(t, err, nil) + m.set = set + + assert.Equal(t, m.Evaluate(p, nil), true) +} + +func TestAfiSafiInMatchPath(t *testing.T) { + condition, err := NewAfiSafiInCondition([]config.AfiSafiType{config.AFI_SAFI_TYPE_L3VPN_IPV4_UNICAST, config.AFI_SAFI_TYPE_L3VPN_IPV6_UNICAST}) + require.NoError(t, err) + + rtExtCom, err := bgp.ParseExtendedCommunity(bgp.EC_SUBTYPE_ROUTE_TARGET, "100:100") + assert.NoError(t, err) + + prefixVPNv4 := bgp.NewLabeledVPNIPAddrPrefix(0, "1.1.1.0/24", *bgp.NewMPLSLabelStack(), bgp.NewRouteDistinguisherTwoOctetAS(100, 100)) + prefixVPNv6 := bgp.NewLabeledVPNIPv6AddrPrefix(0, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", *bgp.NewMPLSLabelStack(), bgp.NewRouteDistinguisherTwoOctetAS(200, 200)) + prefixRTC := bgp.NewRouteTargetMembershipNLRI(100, nil) + prefixv4 := bgp.NewIPAddrPrefix(0, "1.1.1.0/24") + prefixv6 := bgp.NewIPv6AddrPrefix(0, "2001:0db8:85a3:0000:0000:8a2e:0370:7334") + + pathVPNv4 := NewPath(nil, prefixVPNv4, false, []bgp.PathAttributeInterface{bgp.NewPathAttributeExtendedCommunities([]bgp.ExtendedCommunityInterface{rtExtCom})}, time.Time{}, false) + pathVPNv6 := NewPath(nil, prefixVPNv6, false, []bgp.PathAttributeInterface{bgp.NewPathAttributeExtendedCommunities([]bgp.ExtendedCommunityInterface{rtExtCom})}, time.Time{}, false) + pathv4 := NewPath(nil, prefixv4, false, []bgp.PathAttributeInterface{}, time.Time{}, false) + pathv6 := NewPath(nil, prefixv6, false, []bgp.PathAttributeInterface{}, time.Time{}, false) + pathRTC := NewPath(nil, prefixRTC, false, []bgp.PathAttributeInterface{}, time.Time{}, false) + + type Entry struct { + path *Path + shouldMatch bool + } + + for _, entry := range []Entry{ + {pathVPNv4, true}, + {pathVPNv6, true}, + {pathv4, false}, + {pathv6, false}, + {pathRTC, false}, + } { + assert.Equal(t, condition.Evaluate(entry.path, nil), entry.shouldMatch) + } +} + +func TestMultipleStatementPolicy(t *testing.T) { + r := NewRoutingPolicy() + rp := config.RoutingPolicy{ + PolicyDefinitions: []config.PolicyDefinition{config.PolicyDefinition{ + Name: "p1", + Statements: []config.Statement{ + config.Statement{ + Actions: config.Actions{ + BgpActions: config.BgpActions{ + SetMed: "+100", + }, + }, + }, + config.Statement{ + Actions: config.Actions{ + BgpActions: config.BgpActions{ + SetLocalPref: 100, + }, + }, + }, + }, + }, + }, + } + err := r.reload(rp) + assert.Nil(t, err) + + nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0") + + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})} + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + pattrs := []bgp.PathAttributeInterface{origin, aspath, nexthop} + + path := NewPath(nil, nlri, false, pattrs, time.Now(), false) + + pType, newPath := r.policyMap["p1"].Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_NONE, pType) + med, _ := newPath.GetMed() + assert.Equal(t, med, uint32(100)) + localPref, _ := newPath.GetLocalPref() + assert.Equal(t, localPref, uint32(100)) +} |