// 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 TestGetStatement(t *testing.T) { r := NewRoutingPolicy() r.statementMap["statement1"] = &Statement{Name: "statement1"} r.statementMap["statement2"] = &Statement{Name: "statement2"} assert.Equal(t, len(r.GetStatement("")), 2) assert.Equal(t, len(r.GetStatement("statement1")), 1) assert.Equal(t, len(r.GetStatement("unknown")), 0) } func TestGetPolicy(t *testing.T) { r := NewRoutingPolicy() r.policyMap["p1"] = &Policy{Name: "p1"} r.policyMap["p2"] = &Policy{Name: "p2"} assert.Equal(t, len(r.GetPolicy("")), 2) assert.Equal(t, len(r.GetPolicy("p1")), 1) assert.Equal(t, len(r.GetPolicy("unknown")), 0) } 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")) // test if the parseCommunityRegexp function behaves as expected l1 := "6830:24370$" r1, _ := ParseCommunityRegexp("6830:24370$") l2 := "^6830:24370$" r2, _ := ParseCommunityRegexp("^6830:24370$") l3 := "^65001:100$" r3, _ := ParseCommunityRegexp("65001:100") l4 := "^65001:400$" r4, _ := ParseCommunityRegexp("4259905936") l5 := "^[0-9]*:300$" r5, _ := ParseCommunityRegexp("^[0-9]*:300$") l6 := "^" + strconv.Itoa(int(bgp.COMMUNITY_INTERNET)) + ":" + strconv.Itoa(int(bgp.COMMUNITY_INTERNET)) + "$" r6, _ := ParseCommunityRegexp("INTERNET") fmt.Printf("%v %v", l2, r2) assert.Equal(t, l1, r1.String()) assert.Equal(t, l2, r2.String()) assert.Equal(t, l3, r3.String()) assert.Equal(t, l4, r4.String()) assert.Equal(t, l5, r5.String()) assert.Equal(t, l6, r6.String()) } 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 TestPrefixSetMatchV6LabeledwithV6Prefix(t *testing.T) { p1 := config.Prefix{ IpPrefix: "2806:106e:19::/48", MasklengthRange: "48..48", } ps, err := NewPrefixSet(config.PrefixSet{ PrefixSetName: "ps1", PrefixList: []config.Prefix{p1}, }) assert.Nil(t, err) m := &PrefixCondition{ set: ps, } labels := bgp.NewMPLSLabelStack(100, 200) n1 := bgp.NewLabeledIPv6AddrPrefix(48, "2806:106e:19::", *labels) path := NewPath(nil, n1, false, []bgp.PathAttributeInterface{}, time.Now(), false) assert.True(t, m.Evaluate(path, nil)) labels = bgp.NewMPLSLabelStack(100, 200) n2 := bgp.NewLabeledIPv6AddrPrefix(48, "1806:106e:19::", *labels) path = NewPath(nil, n2, 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 TestLargeCommunitiesMatchClearAction(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) a, err := NewLargeCommunityAction(config.SetLargeCommunity{ SetLargeCommunityMethod: config.SetLargeCommunityMethod{ CommunitiesList: []string{ "100:100:100", "100:200:200", }, }, Options: config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE, }) assert.Equal(t, err, nil) p = a.Apply(p, nil) var lc []*bgp.LargeCommunity assert.Equal(t, lc, p.GetLargeCommunities()) } 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)) } func TestNewSingleAsPathMatch(t *testing.T) { r := NewSingleAsPathMatch("^65100_") assert.Equal(t, r.mode, LEFT_MOST) r = NewSingleAsPathMatch("_65100$") assert.Equal(t, r.mode, ORIGIN) r = NewSingleAsPathMatch("_65100_") assert.Equal(t, r.mode, INCLUDE) r = NewSingleAsPathMatch("^65100$") assert.Equal(t, r.mode, ONLY) }