summaryrefslogtreecommitdiffhomepage
path: root/table
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2018-07-07 13:48:38 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2018-07-07 20:44:25 +0900
commitc4775c42510d1f1ddd55036dc19e982712fa6a0b (patch)
tree6ec8b61d4338c809e239e3003a2d32d480898e22 /table
parentb3079759aa13172fcb548a83da9a9653d8d5fed4 (diff)
follow Standard Go Project Layout
https://github.com/golang-standards/project-layout Now you can see clearly what are private and public library code. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Diffstat (limited to 'table')
-rw-r--r--table/adj.go186
-rw-r--r--table/adj_test.go51
-rw-r--r--table/destination.go1041
-rw-r--r--table/destination_test.go441
-rw-r--r--table/message.go502
-rw-r--r--table/message_test.go663
-rw-r--r--table/path.go1179
-rw-r--r--table/path_test.go364
-rw-r--r--table/policy.go3994
-rw-r--r--table/policy_test.go3140
-rw-r--r--table/roa.go60
-rw-r--r--table/table.go451
-rw-r--r--table/table_manager.go356
-rw-r--r--table/table_manager_test.go2281
-rw-r--r--table/table_test.go179
-rw-r--r--table/vrf.go53
16 files changed, 0 insertions, 14941 deletions
diff --git a/table/adj.go b/table/adj.go
deleted file mode 100644
index a0148605..00000000
--- a/table/adj.go
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright (C) 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"
-
- "github.com/osrg/gobgp/packet/bgp"
-)
-
-type AdjRib struct {
- accepted map[bgp.RouteFamily]int
- table map[bgp.RouteFamily]map[string]*Path
-}
-
-func NewAdjRib(rfList []bgp.RouteFamily) *AdjRib {
- table := make(map[bgp.RouteFamily]map[string]*Path)
- for _, rf := range rfList {
- table[rf] = make(map[string]*Path)
- }
- return &AdjRib{
- table: table,
- accepted: make(map[bgp.RouteFamily]int),
- }
-}
-
-func (adj *AdjRib) Update(pathList []*Path) {
- for _, path := range pathList {
- if path == nil || path.IsEOR() {
- continue
- }
- rf := path.GetRouteFamily()
- key := fmt.Sprintf("%d:%s", path.GetNlri().PathIdentifier(), path.getPrefix())
-
- old, found := adj.table[rf][key]
- if path.IsWithdraw {
- if found {
- delete(adj.table[rf], key)
- if !old.IsAsLooped() {
- adj.accepted[rf]--
- }
- }
- } else {
- if found {
- if old.IsAsLooped() && !path.IsAsLooped() {
- adj.accepted[rf]++
- } else if !old.IsAsLooped() && path.IsAsLooped() {
- adj.accepted[rf]--
- }
- } else {
- if !path.IsAsLooped() {
- adj.accepted[rf]++
- }
- }
- if found && old.Equal(path) {
- path.setTimestamp(old.GetTimestamp())
- }
- adj.table[rf][key] = path
- }
- }
-}
-
-func (adj *AdjRib) PathList(rfList []bgp.RouteFamily, accepted bool) []*Path {
- pathList := make([]*Path, 0, adj.Count(rfList))
- for _, rf := range rfList {
- for _, rr := range adj.table[rf] {
- if accepted && rr.IsAsLooped() {
- continue
- }
- pathList = append(pathList, rr)
- }
- }
- return pathList
-}
-
-func (adj *AdjRib) Count(rfList []bgp.RouteFamily) int {
- count := 0
- for _, rf := range rfList {
- if table, ok := adj.table[rf]; ok {
- count += len(table)
- }
- }
- return count
-}
-
-func (adj *AdjRib) Accepted(rfList []bgp.RouteFamily) int {
- count := 0
- for _, rf := range rfList {
- if n, ok := adj.accepted[rf]; ok {
- count += n
- }
- }
- return count
-}
-
-func (adj *AdjRib) Drop(rfList []bgp.RouteFamily) {
- for _, rf := range rfList {
- if _, ok := adj.table[rf]; ok {
- adj.table[rf] = make(map[string]*Path)
- adj.accepted[rf] = 0
- }
- }
-}
-
-func (adj *AdjRib) DropStale(rfList []bgp.RouteFamily) []*Path {
- pathList := make([]*Path, 0, adj.Count(rfList))
- for _, rf := range rfList {
- if table, ok := adj.table[rf]; ok {
- for k, p := range table {
- if p.IsStale() {
- delete(table, k)
- if !p.IsAsLooped() {
- adj.accepted[rf]--
- }
- pathList = append(pathList, p.Clone(true))
- }
- }
- }
- }
- return pathList
-}
-
-func (adj *AdjRib) StaleAll(rfList []bgp.RouteFamily) []*Path {
- pathList := make([]*Path, 0)
- for _, rf := range rfList {
- if table, ok := adj.table[rf]; ok {
- l := make([]*Path, 0, len(table))
- for k, p := range table {
- n := p.Clone(false)
- n.MarkStale(true)
- table[k] = n
- l = append(l, n)
- }
- if len(l) > 0 {
- pathList = append(pathList, l...)
- }
- }
- }
- return pathList
-}
-
-func (adj *AdjRib) Select(family bgp.RouteFamily, accepted bool, option ...TableSelectOption) (*Table, error) {
- m := make(map[string][]*Path)
- pl := adj.PathList([]bgp.RouteFamily{family}, accepted)
- for _, path := range pl {
- key := path.GetNlri().String()
- if _, y := m[key]; y {
- m[key] = append(m[key], path)
- } else {
- m[key] = []*Path{path}
- }
- }
- d := make([]*Destination, 0, len(pl))
- for _, l := range m {
- d = append(d, NewDestination(l[0].GetNlri(), 0, l...))
- }
- tbl := NewTable(family, d...)
- option = append(option, TableSelectOption{adj: true})
- return tbl.Select(option...)
-}
-
-func (adj *AdjRib) TableInfo(family bgp.RouteFamily) (*TableInfo, error) {
- if _, ok := adj.table[family]; !ok {
- return nil, fmt.Errorf("%s unsupported", family)
- }
- c := adj.Count([]bgp.RouteFamily{family})
- a := adj.Accepted([]bgp.RouteFamily{family})
- return &TableInfo{
- NumDestination: c,
- NumPath: c,
- NumAccepted: a,
- }, nil
-}
diff --git a/table/adj_test.go b/table/adj_test.go
deleted file mode 100644
index 45ebcb48..00000000
--- a/table/adj_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2018 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 (
- "testing"
- "time"
-
- "github.com/osrg/gobgp/packet/bgp"
- "github.com/stretchr/testify/assert"
-)
-
-func TestStaleAll(t *testing.T) {
- pi := &PeerInfo{}
- attrs := []bgp.PathAttributeInterface{bgp.NewPathAttributeOrigin(0)}
-
- nlri1 := bgp.NewIPAddrPrefix(24, "20.20.20.0")
- nlri1.SetPathIdentifier(1)
- p1 := NewPath(pi, nlri1, false, attrs, time.Now(), false)
- nlri2 := bgp.NewIPAddrPrefix(24, "20.20.20.0")
- nlri2.SetPathIdentifier(2)
- p2 := NewPath(pi, nlri2, false, attrs, time.Now(), false)
- family := p1.GetRouteFamily()
- families := []bgp.RouteFamily{family}
-
- adj := NewAdjRib(families)
- adj.Update([]*Path{p1, p2})
- assert.Equal(t, len(adj.table[family]), 2)
-
- adj.StaleAll(families)
-
- for _, p := range adj.table[family] {
- assert.True(t, p.IsStale())
- }
-
- adj.DropStale(families)
- assert.Equal(t, len(adj.table[family]), 0)
-}
diff --git a/table/destination.go b/table/destination.go
deleted file mode 100644
index 49dceaa7..00000000
--- a/table/destination.go
+++ /dev/null
@@ -1,1041 +0,0 @@
-// Copyright (C) 2014 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 (
- "bytes"
- "encoding/binary"
- "encoding/json"
- "fmt"
- "net"
- "sort"
-
- log "github.com/sirupsen/logrus"
-
- "github.com/osrg/gobgp/config"
- "github.com/osrg/gobgp/packet/bgp"
-)
-
-var SelectionOptions config.RouteSelectionOptionsConfig
-var UseMultiplePaths config.UseMultiplePathsConfig
-
-type BestPathReason uint8
-
-const (
- BPR_UNKNOWN BestPathReason = iota
- BPR_DISABLED
- BPR_ONLY_PATH
- BPR_REACHABLE_NEXT_HOP
- BPR_HIGHEST_WEIGHT
- BPR_LOCAL_PREF
- BPR_LOCAL_ORIGIN
- BPR_ASPATH
- BPR_ORIGIN
- BPR_MED
- BPR_ASN
- BPR_IGP_COST
- BPR_ROUTER_ID
- BPR_OLDER
- BPR_NON_LLGR_STALE
-)
-
-var BestPathReasonStringMap = map[BestPathReason]string{
- BPR_UNKNOWN: "Unknown",
- BPR_DISABLED: "Bestpath selection disabled",
- BPR_ONLY_PATH: "Only Path",
- BPR_REACHABLE_NEXT_HOP: "Reachable Next Hop",
- BPR_HIGHEST_WEIGHT: "Highest Weight",
- BPR_LOCAL_PREF: "Local Pref",
- BPR_LOCAL_ORIGIN: "Local Origin",
- BPR_ASPATH: "AS Path",
- BPR_ORIGIN: "Origin",
- BPR_MED: "MED",
- BPR_ASN: "ASN",
- BPR_IGP_COST: "IGP Cost",
- BPR_ROUTER_ID: "Router ID",
- BPR_OLDER: "Older",
- BPR_NON_LLGR_STALE: "no LLGR Stale",
-}
-
-func (r *BestPathReason) String() string {
- return BestPathReasonStringMap[*r]
-}
-
-func IpToRadixkey(b []byte, max uint8) string {
- var buffer bytes.Buffer
- for i := 0; i < len(b) && i < int(max); i++ {
- fmt.Fprintf(&buffer, "%08b", b[i])
- }
- return buffer.String()[:max]
-}
-
-func CidrToRadixkey(cidr string) string {
- _, n, _ := net.ParseCIDR(cidr)
- ones, _ := n.Mask.Size()
- return IpToRadixkey(n.IP, uint8(ones))
-}
-
-func AddrToRadixkey(addr bgp.AddrPrefixInterface) string {
- var (
- ip net.IP
- size uint8
- )
- switch T := addr.(type) {
- case *bgp.IPAddrPrefix:
- mask := net.CIDRMask(int(T.Length), net.IPv4len*8)
- ip, size = T.Prefix.Mask(mask).To4(), uint8(T.Length)
- case *bgp.IPv6AddrPrefix:
- mask := net.CIDRMask(int(T.Length), net.IPv6len*8)
- ip, size = T.Prefix.Mask(mask).To16(), uint8(T.Length)
- default:
- return CidrToRadixkey(addr.String())
- }
- return IpToRadixkey(ip, size)
-}
-
-type PeerInfo struct {
- AS uint32
- ID net.IP
- LocalAS uint32
- LocalID net.IP
- Address net.IP
- LocalAddress net.IP
- RouteReflectorClient bool
- RouteReflectorClusterID net.IP
- MultihopTtl uint8
- Confederation bool
-}
-
-func (lhs *PeerInfo) Equal(rhs *PeerInfo) bool {
- if lhs == rhs {
- return true
- }
-
- if rhs == nil {
- return false
- }
-
- if (lhs.AS == rhs.AS) && lhs.ID.Equal(rhs.ID) && lhs.LocalID.Equal(rhs.LocalID) && lhs.Address.Equal(rhs.Address) {
- return true
- }
- return false
-}
-
-func (i *PeerInfo) String() string {
- if i.Address == nil {
- return "local"
- }
- s := bytes.NewBuffer(make([]byte, 0, 64))
- s.WriteString(fmt.Sprintf("{ %s | ", i.Address))
- s.WriteString(fmt.Sprintf("as: %d", i.AS))
- s.WriteString(fmt.Sprintf(", id: %s", i.ID))
- if i.RouteReflectorClient {
- s.WriteString(fmt.Sprintf(", cluster-id: %s", i.RouteReflectorClusterID))
- }
- s.WriteString(" }")
- return s.String()
-}
-
-func NewPeerInfo(g *config.Global, p *config.Neighbor) *PeerInfo {
- clusterID := net.ParseIP(string(p.RouteReflector.State.RouteReflectorClusterId)).To4()
- // exclude zone info
- naddr, _ := net.ResolveIPAddr("ip", p.State.NeighborAddress)
- return &PeerInfo{
- AS: p.Config.PeerAs,
- LocalAS: g.Config.As,
- LocalID: net.ParseIP(g.Config.RouterId).To4(),
- RouteReflectorClient: p.RouteReflector.Config.RouteReflectorClient,
- Address: naddr.IP,
- RouteReflectorClusterID: clusterID,
- MultihopTtl: p.EbgpMultihop.Config.MultihopTtl,
- Confederation: p.IsConfederationMember(g),
- }
-}
-
-type Destination struct {
- routeFamily bgp.RouteFamily
- nlri bgp.AddrPrefixInterface
- knownPathList []*Path
- localIdMap *Bitmap
-}
-
-func NewDestination(nlri bgp.AddrPrefixInterface, mapSize int, known ...*Path) *Destination {
- d := &Destination{
- routeFamily: bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI()),
- nlri: nlri,
- knownPathList: known,
- localIdMap: NewBitmap(mapSize),
- }
- // the id zero means id is not allocated yet.
- if mapSize != 0 {
- d.localIdMap.Flag(0)
- }
- return d
-}
-
-func (dd *Destination) Family() bgp.RouteFamily {
- return dd.routeFamily
-}
-
-func (dd *Destination) setRouteFamily(routeFamily bgp.RouteFamily) {
- dd.routeFamily = routeFamily
-}
-
-func (dd *Destination) GetNlri() bgp.AddrPrefixInterface {
- return dd.nlri
-}
-
-func (dd *Destination) setNlri(nlri bgp.AddrPrefixInterface) {
- dd.nlri = nlri
-}
-
-func (dd *Destination) GetAllKnownPathList() []*Path {
- return dd.knownPathList
-}
-
-func rsFilter(id string, as uint32, path *Path) bool {
- isASLoop := func(as uint32, path *Path) bool {
- for _, v := range path.GetAsList() {
- if as == v {
- return true
- }
- }
- return false
- }
-
- if id != GLOBAL_RIB_NAME && (path.GetSource().Address.String() == id || isASLoop(as, path)) {
- return true
- }
- return false
-}
-
-func (dd *Destination) GetKnownPathList(id string, as uint32) []*Path {
- list := make([]*Path, 0, len(dd.knownPathList))
- for _, p := range dd.knownPathList {
- if rsFilter(id, as, p) {
- continue
- }
- list = append(list, p)
- }
- return list
-}
-
-func getBestPath(id string, as uint32, pathList []*Path) *Path {
- for _, p := range pathList {
- if rsFilter(id, as, p) {
- continue
- }
- return p
- }
- return nil
-}
-
-func (dd *Destination) GetBestPath(id string, as uint32) *Path {
- p := getBestPath(id, as, dd.knownPathList)
- if p == nil || p.IsNexthopInvalid {
- return nil
- }
- return p
-}
-
-func (dd *Destination) GetMultiBestPath(id string) []*Path {
- return getMultiBestPath(id, dd.knownPathList)
-}
-
-// Calculates best-path among known paths for this destination.
-//
-// Modifies destination's state related to stored paths. Removes withdrawn
-// paths from known paths. Also, adds new paths to known paths.
-func (dest *Destination) Calculate(newPath *Path) *Update {
- oldKnownPathList := make([]*Path, len(dest.knownPathList))
- copy(oldKnownPathList, dest.knownPathList)
-
- if newPath.IsWithdraw {
- p := dest.explicitWithdraw(newPath)
- if p != nil {
- if id := p.GetNlri().PathLocalIdentifier(); id != 0 {
- dest.localIdMap.Unflag(uint(id))
- }
- }
- } else {
- dest.implicitWithdraw(newPath)
- dest.knownPathList = append(dest.knownPathList, newPath)
- }
-
- for _, path := range dest.knownPathList {
- if path.GetNlri().PathLocalIdentifier() == 0 {
- id, err := dest.localIdMap.FindandSetZeroBit()
- if err != nil {
- dest.localIdMap.Expand()
- id, _ = dest.localIdMap.FindandSetZeroBit()
- }
- path.GetNlri().SetPathLocalIdentifier(uint32(id))
- }
- }
- // Compute new best path
- dest.computeKnownBestPath()
-
- l := make([]*Path, len(dest.knownPathList))
- copy(l, dest.knownPathList)
- return &Update{
- KnownPathList: l,
- OldKnownPathList: oldKnownPathList,
- }
-}
-
-// Removes withdrawn paths.
-//
-// Note:
-// We may have disproportionate number of withdraws compared to know paths
-// since not all paths get installed into the table due to bgp policy and
-// we can receive withdraws for such paths and withdrawals may not be
-// stopped by the same policies.
-//
-func (dest *Destination) explicitWithdraw(withdraw *Path) *Path {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Key": dest.GetNlri().String(),
- }).Debug("Removing withdrawals")
-
- // If we have some withdrawals and no know-paths, it means it is safe to
- // delete these withdraws.
- if len(dest.knownPathList) == 0 {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Key": dest.GetNlri().String(),
- }).Debug("Found withdrawals for path(s) that did not get installed")
- return nil
- }
-
- // Match all withdrawals from destination paths.
- isFound := -1
- for i, path := range dest.knownPathList {
- // We have a match if the source and path-id are same.
- if path.GetSource().Equal(withdraw.GetSource()) && path.GetNlri().PathIdentifier() == withdraw.GetNlri().PathIdentifier() {
- isFound = i
- withdraw.GetNlri().SetPathLocalIdentifier(path.GetNlri().PathLocalIdentifier())
- }
- }
-
- // We do no have any match for this withdraw.
- if isFound == -1 {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Key": dest.GetNlri().String(),
- "Path": withdraw,
- }).Warn("No matching path for withdraw found, may be path was not installed into table")
- return nil
- } else {
- p := dest.knownPathList[isFound]
- dest.knownPathList = append(dest.knownPathList[:isFound], dest.knownPathList[isFound+1:]...)
- return p
- }
-}
-
-// Identifies which of known paths are old and removes them.
-//
-// Known paths will no longer have paths whose new version is present in
-// new paths.
-func (dest *Destination) implicitWithdraw(newPath *Path) {
- found := -1
- for i, path := range dest.knownPathList {
- if newPath.NoImplicitWithdraw() {
- continue
- }
- // Here we just check if source is same and not check if path
- // version num. as newPaths are implicit withdrawal of old
- // paths and when doing RouteRefresh (not EnhancedRouteRefresh)
- // we get same paths again.
- if newPath.GetSource().Equal(path.GetSource()) && newPath.GetNlri().PathIdentifier() == path.GetNlri().PathIdentifier() {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Key": dest.GetNlri().String(),
- "Path": path,
- }).Debug("Implicit withdrawal of old path, since we have learned new path from the same peer")
-
- found = i
- newPath.GetNlri().SetPathLocalIdentifier(path.GetNlri().PathLocalIdentifier())
- break
- }
- }
- if found != -1 {
- dest.knownPathList = append(dest.knownPathList[:found], dest.knownPathList[found+1:]...)
- }
-}
-
-func (dest *Destination) computeKnownBestPath() (*Path, BestPathReason, error) {
- if SelectionOptions.DisableBestPathSelection {
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debug("computeKnownBestPath skipped")
- return nil, BPR_DISABLED, nil
- }
-
- // If we do not have any paths to this destination, then we do not have
- // new best path.
- if len(dest.knownPathList) == 0 {
- return nil, BPR_UNKNOWN, nil
- }
-
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debugf("computeKnownBestPath knownPathList: %d", len(dest.knownPathList))
-
- // We pick the first path as current best path. This helps in breaking
- // tie between two new paths learned in one cycle for which best-path
- // calculation steps lead to tie.
- if len(dest.knownPathList) == 1 {
- // If the first path has the invalidated next-hop, which evaluated by
- // IGP, returns no path with the reason of the next-hop reachability.
- if dest.knownPathList[0].IsNexthopInvalid {
- return nil, BPR_REACHABLE_NEXT_HOP, nil
- }
- return dest.knownPathList[0], BPR_ONLY_PATH, nil
- }
- dest.sort()
- newBest := dest.knownPathList[0]
- // If the first path has the invalidated next-hop, which evaluated by IGP,
- // returns no path with the reason of the next-hop reachability.
- if dest.knownPathList[0].IsNexthopInvalid {
- return nil, BPR_REACHABLE_NEXT_HOP, nil
- }
- return newBest, newBest.reason, nil
-}
-
-func (dst *Destination) sort() {
- sort.SliceStable(dst.knownPathList, func(i, j int) bool {
- //Compares given paths and returns best path.
- //
- //Parameters:
- // -`path1`: first path to compare
- // -`path2`: second path to compare
- //
- // Best path processing will involve following steps:
- // 1. Select a path with a reachable next hop.
- // 2. Select the path with the highest weight.
- // 3. If path weights are the same, select the path with the highest
- // local preference value.
- // 4. Prefer locally originated routes (network routes, redistributed
- // routes, or aggregated routes) over received routes.
- // 5. Select the route with the shortest AS-path length.
- // 6. If all paths have the same AS-path length, select the path based
- // on origin: IGP is preferred over EGP; EGP is preferred over
- // Incomplete.
- // 7. If the origins are the same, select the path with lowest MED
- // value.
- // 8. If the paths have the same MED values, select the path learned
- // via EBGP over one learned via IBGP.
- // 9. Select the route with the lowest IGP cost to the next hop.
- // 10. Select the route received from the peer with the lowest BGP
- // router ID.
- //
- // Returns None if best-path among given paths cannot be computed else best
- // path.
- // Assumes paths from NC has source equal to None.
- //
-
- path1 := dst.knownPathList[i]
- path2 := dst.knownPathList[j]
-
- var better *Path
- reason := BPR_UNKNOWN
-
- // draft-uttaro-idr-bgp-persistence-02
- if better == nil {
- better = compareByLLGRStaleCommunity(path1, path2)
- reason = BPR_NON_LLGR_STALE
- }
- // Follow best path calculation algorithm steps.
- // compare by reachability
- if better == nil {
- better = compareByReachableNexthop(path1, path2)
- reason = BPR_REACHABLE_NEXT_HOP
- }
- if better == nil {
- better = compareByHighestWeight(path1, path2)
- reason = BPR_HIGHEST_WEIGHT
- }
- if better == nil {
- better = compareByLocalPref(path1, path2)
- reason = BPR_LOCAL_PREF
- }
- if better == nil {
- better = compareByLocalOrigin(path1, path2)
- reason = BPR_LOCAL_ORIGIN
- }
- if better == nil {
- better = compareByASPath(path1, path2)
- reason = BPR_ASPATH
- }
- if better == nil {
- better = compareByOrigin(path1, path2)
- reason = BPR_ORIGIN
- }
- if better == nil {
- better = compareByMED(path1, path2)
- reason = BPR_MED
- }
- if better == nil {
- better = compareByASNumber(path1, path2)
- reason = BPR_ASN
- }
- if better == nil {
- better = compareByIGPCost(path1, path2)
- reason = BPR_IGP_COST
- }
- if better == nil {
- better = compareByAge(path1, path2)
- reason = BPR_OLDER
- }
- if better == nil {
- var e error = nil
- better, e = compareByRouterID(path1, path2)
- if e != nil {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Error": e,
- }).Error("Could not get best path by comparing router ID")
- }
- reason = BPR_ROUTER_ID
- }
- if better == nil {
- reason = BPR_UNKNOWN
- better = path1
- }
-
- better.reason = reason
-
- return better == path1
- })
-}
-
-type Update struct {
- KnownPathList []*Path
- OldKnownPathList []*Path
-}
-
-func getMultiBestPath(id string, pathList []*Path) []*Path {
- list := make([]*Path, 0, len(pathList))
- var best *Path
- for _, p := range pathList {
- if !p.IsNexthopInvalid {
- if best == nil {
- best = p
- list = append(list, p)
- } else if best.Compare(p) == 0 {
- list = append(list, p)
- }
- }
- }
- return list
-}
-
-func (u *Update) GetWithdrawnPath() []*Path {
- if len(u.KnownPathList) == len(u.OldKnownPathList) {
- return nil
- }
-
- l := make([]*Path, 0, len(u.OldKnownPathList))
-
- for _, p := range u.OldKnownPathList {
- y := func() bool {
- for _, old := range u.KnownPathList {
- if p == old {
- return true
- }
- }
- return false
- }()
- if !y {
- l = append(l, p.Clone(true))
- }
- }
- return l
-}
-
-func (u *Update) GetChanges(id string, as uint32, peerDown bool) (*Path, *Path, []*Path) {
- best, old := func(id string) (*Path, *Path) {
- old := getBestPath(id, as, u.OldKnownPathList)
- best := getBestPath(id, as, u.KnownPathList)
- if best != nil && best.Equal(old) {
- // RFC4684 3.2. Intra-AS VPN Route Distribution
- // When processing RT membership NLRIs received from internal iBGP
- // peers, it is necessary to consider all available iBGP paths for a
- // given RT prefix, for building the outbound route filter, and not just
- // the best path.
- if best.GetRouteFamily() == bgp.RF_RTC_UC {
- return best, old
- }
- // For BGP Nexthop Tracking, checks if the nexthop reachability
- // was changed or not.
- if best.IsNexthopInvalid != old.IsNexthopInvalid {
- // If the nexthop of the best path became unreachable, we need
- // to withdraw that path.
- if best.IsNexthopInvalid {
- return best.Clone(true), old
- }
- return best, old
- }
- return nil, old
- }
- if best == nil {
- if old == nil {
- return nil, nil
- }
- if peerDown {
- // withdraws were generated by peer
- // down so paths are not in knowpath
- // or adjin.
- old.IsWithdraw = true
- return old, old
- }
- return old.Clone(true), old
- }
- return best, old
- }(id)
-
- var multi []*Path
-
- if id == GLOBAL_RIB_NAME && UseMultiplePaths.Enabled {
- diff := func(lhs, rhs []*Path) bool {
- if len(lhs) != len(rhs) {
- return true
- }
- for idx, l := range lhs {
- if !l.Equal(rhs[idx]) {
- return true
- }
- }
- return false
- }
- oldM := getMultiBestPath(id, u.OldKnownPathList)
- newM := getMultiBestPath(id, u.KnownPathList)
- if diff(oldM, newM) {
- multi = newM
- if len(newM) == 0 {
- multi = []*Path{best}
- }
- }
- }
- return best, old, multi
-}
-
-func compareByLLGRStaleCommunity(path1, path2 *Path) *Path {
- p1 := path1.IsLLGRStale()
- p2 := path2.IsLLGRStale()
- if p1 == p2 {
- return nil
- } else if p1 {
- return path2
- }
- return path1
-}
-
-func compareByReachableNexthop(path1, path2 *Path) *Path {
- // Compares given paths and selects best path based on reachable next-hop.
- //
- // If no path matches this criteria, return nil.
- // For BGP Nexthop Tracking, evaluates next-hop is validated by IGP.
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debugf("enter compareByReachableNexthop -- path1: %s, path2: %s", path1, path2)
-
- if path1.IsNexthopInvalid && !path2.IsNexthopInvalid {
- return path2
- } else if !path1.IsNexthopInvalid && path2.IsNexthopInvalid {
- return path1
- }
-
- return nil
-}
-
-func compareByHighestWeight(path1, path2 *Path) *Path {
- // Selects a path with highest weight.
- //
- // Weight is BGPS specific parameter. It is local to the router on which it
- // is configured.
- // Return:
- // nil if best path among given paths cannot be decided, else best path.
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debugf("enter compareByHighestWeight -- path1: %s, path2: %s", path1, path2)
- return nil
-}
-
-func compareByLocalPref(path1, path2 *Path) *Path {
- // Selects a path with highest local-preference.
- //
- // Unlike the weight attribute, which is only relevant to the local
- // router, local preference is an attribute that routers exchange in the
- // same AS. Highest local-pref is preferred. If we cannot decide,
- // we return None.
- //
- // # Default local-pref values is 100
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debug("enter compareByLocalPref")
- localPref1, _ := path1.GetLocalPref()
- localPref2, _ := path2.GetLocalPref()
- // Highest local-preference value is preferred.
- if localPref1 > localPref2 {
- return path1
- } else if localPref1 < localPref2 {
- return path2
- } else {
- return nil
- }
-}
-
-func compareByLocalOrigin(path1, path2 *Path) *Path {
-
- // Select locally originating path as best path.
- // Locally originating routes are network routes, redistributed routes,
- // or aggregated routes.
- // Returns None if given paths have same source.
- //
- // If both paths are from same sources we cannot compare them here.
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debug("enter compareByLocalOrigin")
- if path1.GetSource().Equal(path2.GetSource()) {
- return nil
- }
-
- // Here we consider prefix from NC as locally originating static route.
- // Hence it is preferred.
- if path1.IsLocal() {
- return path1
- }
-
- if path2.IsLocal() {
- return path2
- }
- return nil
-}
-
-func compareByASPath(path1, path2 *Path) *Path {
- // Calculated the best-paths by comparing as-path lengths.
- //
- // Shortest as-path length is preferred. If both path have same lengths,
- // we return None.
- if SelectionOptions.IgnoreAsPathLength {
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debug("compareByASPath -- skip")
- return nil
- }
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debug("enter compareByASPath")
- attribute1 := path1.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- attribute2 := path2.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
-
- // With addpath support, we could compare paths from API don't
- // AS_PATH. No need to warn here.
- if !path1.IsLocal() && !path2.IsLocal() && (attribute1 == nil || attribute2 == nil) {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Key": "compareByASPath",
- "ASPath1": attribute1,
- "ASPath2": attribute2,
- }).Warn("can't compare ASPath because it's not present")
- }
-
- l1 := path1.GetAsPathLen()
- l2 := path2.GetAsPathLen()
-
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debugf("compareByASPath -- l1: %d, l2: %d", l1, l2)
- if l1 > l2 {
- return path2
- } else if l1 < l2 {
- return path1
- } else {
- return nil
- }
-}
-
-func compareByOrigin(path1, path2 *Path) *Path {
- // Select the best path based on origin attribute.
- //
- // IGP is preferred over EGP; EGP is preferred over Incomplete.
- // If both paths have same origin, we return None.
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debug("enter compareByOrigin")
- attribute1 := path1.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- attribute2 := path2.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
-
- if attribute1 == nil || attribute2 == nil {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Key": "compareByOrigin",
- "Origin1": attribute1,
- "Origin2": attribute2,
- }).Error("can't compare origin because it's not present")
- return nil
- }
-
- origin1 := attribute1.(*bgp.PathAttributeOrigin).Value
- origin2 := attribute2.(*bgp.PathAttributeOrigin).Value
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debugf("compareByOrigin -- origin1: %d, origin2: %d", origin1, origin2)
-
- // If both paths have same origins
- if origin1 == origin2 {
- return nil
- } else if origin1 < origin2 {
- return path1
- } else {
- return path2
- }
-}
-
-func compareByMED(path1, path2 *Path) *Path {
- // Select the path based with lowest MED value.
- //
- // If both paths have same MED, return None.
- // By default, a route that arrives with no MED value is treated as if it
- // had a MED of 0, the most preferred value.
- // RFC says lower MED is preferred over higher MED value.
- // compare MED among not only same AS path but also all path,
- // like bgp always-compare-med
-
- isInternal := func() bool { return path1.GetAsPathLen() == 0 && path2.GetAsPathLen() == 0 }()
-
- isSameAS := func() bool {
- firstAS := func(path *Path) uint32 {
- if asPath := path.GetAsPath(); asPath != nil {
- for _, v := range asPath.Value {
- segType := v.GetType()
- asList := v.GetAS()
- if len(asList) == 0 {
- continue
- }
- switch segType {
- case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ:
- continue
- }
- return asList[0]
- }
- }
- return 0
- }
- return firstAS(path1) != 0 && firstAS(path1) == firstAS(path2)
- }()
-
- if SelectionOptions.AlwaysCompareMed || isInternal || isSameAS {
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debug("enter compareByMED")
- getMed := func(path *Path) uint32 {
- attribute := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- if attribute == nil {
- return 0
- }
- med := attribute.(*bgp.PathAttributeMultiExitDisc).Value
- return med
- }
-
- med1 := getMed(path1)
- med2 := getMed(path2)
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debugf("compareByMED -- med1: %d, med2: %d", med1, med2)
- if med1 == med2 {
- return nil
- } else if med1 < med2 {
- return path1
- }
- return path2
- } else {
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debugf("skip compareByMED %v %v %v", SelectionOptions.AlwaysCompareMed, isInternal, isSameAS)
- return nil
- }
-}
-
-func compareByASNumber(path1, path2 *Path) *Path {
-
- //Select the path based on source (iBGP/eBGP) peer.
- //
- //eBGP path is preferred over iBGP. If both paths are from same kind of
- //peers, return None.
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debug("enter compareByASNumber")
-
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debugf("compareByASNumber -- p1Asn: %d, p2Asn: %d", path1.GetSource().AS, path2.GetSource().AS)
- // Path from confederation member should be treated as internal (IBGP learned) path.
- isIBGP1 := path1.GetSource().Confederation || path1.IsIBGP()
- isIBGP2 := path2.GetSource().Confederation || path2.IsIBGP()
- // If one path is from ibgp peer and another is from ebgp peer, take the ebgp path.
- if isIBGP1 != isIBGP2 {
- if isIBGP1 {
- return path2
- }
- return path1
- }
-
- // If both paths are from ebgp or ibpg peers, we cannot decide.
- return nil
-}
-
-func compareByIGPCost(path1, path2 *Path) *Path {
- // Select the route with the lowest IGP cost to the next hop.
- //
- // Return None if igp cost is same.
- // Currently BGPS has no concept of IGP and IGP cost.
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debugf("enter compareByIGPCost -- path1: %v, path2: %v", path1, path2)
- return nil
-}
-
-func compareByRouterID(path1, path2 *Path) (*Path, error) {
- // Select the route received from the peer with the lowest BGP router ID.
- //
- // If both paths are eBGP paths, then we do not do any tie breaking, i.e we do
- // not pick best-path based on this criteria.
- // RFC: http://tools.ietf.org/html/rfc5004
- // We pick best path between two iBGP paths as usual.
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Debug("enter compareByRouterID")
-
- // If both paths are from NC we have same router Id, hence cannot compare.
- if path1.IsLocal() && path2.IsLocal() {
- return nil, nil
- }
-
- // If both paths are from eBGP peers, then according to RFC we need
- // not tie break using router id.
- if !SelectionOptions.ExternalCompareRouterId && !path1.IsIBGP() && !path2.IsIBGP() {
- return nil, nil
- }
-
- if !SelectionOptions.ExternalCompareRouterId && path1.IsIBGP() != path2.IsIBGP() {
- return nil, fmt.Errorf("This method does not support comparing ebgp with ibgp path")
- }
-
- // At least one path is not coming from NC, so we get local bgp id.
- id1 := binary.BigEndian.Uint32(path1.GetSource().ID)
- id2 := binary.BigEndian.Uint32(path2.GetSource().ID)
-
- // If both router ids are same/equal we cannot decide.
- // This case is possible since router ids are arbitrary.
- if id1 == id2 {
- return nil, nil
- } else if id1 < id2 {
- return path1, nil
- } else {
- return path2, nil
- }
-}
-
-func compareByAge(path1, path2 *Path) *Path {
- if !path1.IsIBGP() && !path2.IsIBGP() && !SelectionOptions.ExternalCompareRouterId {
- age1 := path1.GetTimestamp().UnixNano()
- age2 := path2.GetTimestamp().UnixNano()
- if age1 == age2 {
- return nil
- } else if age1 < age2 {
- return path1
- }
- return path2
- }
- return nil
-}
-
-func (dest *Destination) String() string {
- return fmt.Sprintf("Destination NLRI: %s", dest.nlri.String())
-}
-
-type DestinationSelectOption struct {
- ID string
- AS uint32
- VRF *Vrf
- adj bool
- Best bool
- MultiPath bool
-}
-
-func (d *Destination) MarshalJSON() ([]byte, error) {
- return json.Marshal(d.GetAllKnownPathList())
-}
-
-func (d *Destination) Select(option ...DestinationSelectOption) *Destination {
- id := GLOBAL_RIB_NAME
- var vrf *Vrf
- adj := false
- best := false
- mp := false
- as := uint32(0)
- for _, o := range option {
- if o.ID != "" {
- id = o.ID
- }
- if o.VRF != nil {
- vrf = o.VRF
- }
- adj = o.adj
- best = o.Best
- mp = o.MultiPath
- as = o.AS
- }
- var paths []*Path
- if adj {
- paths = make([]*Path, len(d.knownPathList))
- copy(paths, d.knownPathList)
- } else {
- paths = d.GetKnownPathList(id, as)
- if vrf != nil {
- ps := make([]*Path, 0, len(paths))
- for _, p := range paths {
- if CanImportToVrf(vrf, p) {
- ps = append(ps, p.ToLocal())
- }
- }
- paths = ps
- }
- if len(paths) == 0 {
- return nil
- }
- if best {
- if !mp {
- paths = []*Path{paths[0]}
- } else {
- ps := make([]*Path, 0, len(paths))
- var best *Path
- for _, p := range paths {
- if best == nil {
- best = p
- ps = append(ps, p)
- } else if best.Compare(p) == 0 {
- ps = append(ps, p)
- }
- }
- paths = ps
- }
- }
- }
- return NewDestination(d.nlri, 0, paths...)
-}
diff --git a/table/destination_test.go b/table/destination_test.go
deleted file mode 100644
index b5a42007..00000000
--- a/table/destination_test.go
+++ /dev/null
@@ -1,441 +0,0 @@
-// Copyright (C) 2014 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"
- "fmt"
- "net"
- "testing"
- "time"
-
- "github.com/osrg/gobgp/packet/bgp"
- "github.com/stretchr/testify/assert"
-)
-
-func TestDestinationNewIPv4(t *testing.T) {
- peerD := DestCreatePeer()
- pathD := DestCreatePath(peerD)
- ipv4d := NewDestination(pathD[0].GetNlri(), 0)
- assert.NotNil(t, ipv4d)
-}
-func TestDestinationNewIPv6(t *testing.T) {
- peerD := DestCreatePeer()
- pathD := DestCreatePath(peerD)
- ipv6d := NewDestination(pathD[0].GetNlri(), 0)
- assert.NotNil(t, ipv6d)
-}
-
-func TestDestinationSetRouteFamily(t *testing.T) {
- dd := &Destination{}
- dd.setRouteFamily(bgp.RF_IPv4_UC)
- rf := dd.Family()
- assert.Equal(t, rf, bgp.RF_IPv4_UC)
-}
-func TestDestinationGetRouteFamily(t *testing.T) {
- dd := &Destination{}
- dd.setRouteFamily(bgp.RF_IPv6_UC)
- rf := dd.Family()
- assert.Equal(t, rf, bgp.RF_IPv6_UC)
-}
-func TestDestinationSetNlri(t *testing.T) {
- dd := &Destination{}
- nlri := bgp.NewIPAddrPrefix(24, "13.2.3.1")
- dd.setNlri(nlri)
- r_nlri := dd.GetNlri()
- assert.Equal(t, r_nlri, nlri)
-}
-func TestDestinationGetNlri(t *testing.T) {
- dd := &Destination{}
- nlri := bgp.NewIPAddrPrefix(24, "10.110.123.1")
- dd.setNlri(nlri)
- r_nlri := dd.GetNlri()
- assert.Equal(t, r_nlri, nlri)
-}
-
-func TestCalculate2(t *testing.T) {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{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.NewIPAddrPrefix(24, "10.10.0.0")
-
- // peer1 sends normal update message 10.10.0.0/24
- update1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri})
- peer1 := &PeerInfo{AS: 1, Address: net.IP{1, 1, 1, 1}}
- path1 := ProcessMessage(update1, peer1, time.Now())[0]
-
- d := NewDestination(nlri, 0)
- d.Calculate(path1)
-
- // suppose peer2 sends grammaatically correct but semantically flawed update message
- // which has a withdrawal nlri not advertised before
- update2 := bgp.NewBGPUpdateMessage([]*bgp.IPAddrPrefix{nlri}, pathAttributes, nil)
- peer2 := &PeerInfo{AS: 2, Address: net.IP{2, 2, 2, 2}}
- path2 := ProcessMessage(update2, peer2, time.Now())[0]
- assert.Equal(t, path2.IsWithdraw, true)
-
- d.Calculate(path2)
-
- // we have a path from peer1 here
- assert.Equal(t, len(d.knownPathList), 1)
-
- // after that, new update with the same nlri comes from peer2
- update3 := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri})
- path3 := ProcessMessage(update3, peer2, time.Now())[0]
- assert.Equal(t, path3.IsWithdraw, false)
-
- d.Calculate(path3)
-
- // this time, we have paths from peer1 and peer2
- assert.Equal(t, len(d.knownPathList), 2)
-
- // now peer3 sends normal update message 10.10.0.0/24
- peer3 := &PeerInfo{AS: 3, Address: net.IP{3, 3, 3, 3}}
- update4 := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri})
- path4 := ProcessMessage(update4, peer3, time.Now())[0]
-
- d.Calculate(path4)
-
- // we must have paths from peer1, peer2 and peer3
- assert.Equal(t, len(d.knownPathList), 3)
-}
-
-func TestMedTieBreaker(t *testing.T) {
- nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0")
-
- p0 := func() *Path {
- aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65002}), bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65003, 65004})})
- attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(0)}
- return NewPath(nil, nlri, false, attrs, time.Now(), false)
- }()
-
- p1 := func() *Path {
- aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65002}), bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65003, 65005})})
- attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(10)}
- return NewPath(nil, nlri, false, attrs, time.Now(), false)
- }()
-
- // same AS
- assert.Equal(t, compareByMED(p0, p1), p0)
-
- p2 := func() *Path {
- aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65003})})
- attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(10)}
- return NewPath(nil, nlri, false, attrs, time.Now(), false)
- }()
-
- // different AS
- assert.Equal(t, compareByMED(p0, p2), (*Path)(nil))
-
- p3 := func() *Path {
- aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, []uint32{65003, 65004}), bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65003})})
- attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(0)}
- return NewPath(nil, nlri, false, attrs, time.Now(), false)
- }()
-
- p4 := func() *Path {
- aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65002}), bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, []uint32{65005, 65006})})
- attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(10)}
- return NewPath(nil, nlri, false, attrs, time.Now(), false)
- }()
-
- // ignore confed
- assert.Equal(t, compareByMED(p3, p4), p3)
-
- p5 := func() *Path {
- attrs := []bgp.PathAttributeInterface{bgp.NewPathAttributeMultiExitDisc(0)}
- return NewPath(nil, nlri, false, attrs, time.Now(), false)
- }()
-
- p6 := func() *Path {
- attrs := []bgp.PathAttributeInterface{bgp.NewPathAttributeMultiExitDisc(10)}
- return NewPath(nil, nlri, false, attrs, time.Now(), false)
- }()
-
- // no aspath
- assert.Equal(t, compareByMED(p5, p6), p5)
-}
-
-func TestTimeTieBreaker(t *testing.T) {
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{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.NewIPAddrPrefix(24, "10.10.0.0")
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri})
- peer1 := &PeerInfo{AS: 2, LocalAS: 1, Address: net.IP{1, 1, 1, 1}, ID: net.IP{1, 1, 1, 1}}
- path1 := ProcessMessage(updateMsg, peer1, time.Now())[0]
-
- peer2 := &PeerInfo{AS: 2, LocalAS: 1, Address: net.IP{2, 2, 2, 2}, ID: net.IP{2, 2, 2, 2}} // weaker router-id
- path2 := ProcessMessage(updateMsg, peer2, time.Now().Add(-1*time.Hour))[0] // older than path1
-
- d := NewDestination(nlri, 0)
- d.Calculate(path1)
- d.Calculate(path2)
-
- assert.Equal(t, len(d.knownPathList), 2)
- assert.Equal(t, true, d.GetBestPath("", 0).GetSource().ID.Equal(net.IP{2, 2, 2, 2})) // path from peer2 win
-
- // this option disables tie breaking by age
- SelectionOptions.ExternalCompareRouterId = true
- d = NewDestination(nlri, 0)
- d.Calculate(path1)
- d.Calculate(path2)
-
- assert.Equal(t, len(d.knownPathList), 2)
- assert.Equal(t, true, d.GetBestPath("", 0).GetSource().ID.Equal(net.IP{1, 1, 1, 1})) // path from peer1 win
-}
-
-func DestCreatePeer() []*PeerInfo {
- peerD1 := &PeerInfo{AS: 65000}
- peerD2 := &PeerInfo{AS: 65001}
- peerD3 := &PeerInfo{AS: 65002}
- peerD := []*PeerInfo{peerD1, peerD2, peerD3}
- return peerD
-}
-
-func DestCreatePath(peerD []*PeerInfo) []*Path {
- bgpMsgD1 := updateMsgD1()
- bgpMsgD2 := updateMsgD2()
- bgpMsgD3 := updateMsgD3()
- pathD := make([]*Path, 3)
- for i, msg := range []*bgp.BGPMessage{bgpMsgD1, bgpMsgD2, bgpMsgD3} {
- updateMsgD := msg.Body.(*bgp.BGPUpdate)
- nlriList := updateMsgD.NLRI
- pathAttributes := updateMsgD.PathAttributes
- nlri_info := nlriList[0]
- pathD[i] = NewPath(peerD[i], nlri_info, false, pathAttributes, time.Now(), false)
- }
- return pathD
-}
-
-func updateMsgD1() *bgp.BGPMessage {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65000})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
- return updateMsg
-}
-
-func updateMsgD2() *bgp.BGPMessage {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65100})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.100.1")
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "20.20.20.0")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
- return updateMsg
-}
-func updateMsgD3() *bgp.BGPMessage {
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65100})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.150.1")
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "30.30.30.0")}
- w1 := bgp.NewIPAddrPrefix(23, "40.40.40.0")
- withdrawnRoutes := []*bgp.IPAddrPrefix{w1}
- updateMsg := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
- return updateMsg
-}
-
-func TestRadixkey(t *testing.T) {
- assert.Equal(t, "000010100000001100100000", CidrToRadixkey("10.3.32.0/24"))
- assert.Equal(t, "000010100000001100100000", IpToRadixkey(net.ParseIP("10.3.32.0").To4(), 24))
- assert.Equal(t, "000010100000001100100000", IpToRadixkey(net.ParseIP("10.3.32.0").To4(), 24))
- assert.Equal(t, CidrToRadixkey("::ffff:0.0.0.0/96")+"000010100000001100100000", CidrToRadixkey("::ffff:10.3.32.0/120"))
-}
-
-func TestIpToRadixkey(t *testing.T) {
- for i := byte(0); i < 255; i += 3 {
- for y := byte(1); y < 128; y *= 2 {
- ip := net.IPv4(i, i+2, i+3, i-y)
- for n := uint8(16); n <= 32; n += 2 {
- exp := CidrToRadixkey(fmt.Sprintf("%v/%d", ip.To4(), n))
- got := IpToRadixkey(ip.To4(), n)
- if exp != got {
- t.Fatalf(`exp %v; got %v`, exp, got)
- }
- }
- for n := uint8(116); n <= 128; n += 2 {
- exp := CidrToRadixkey(fmt.Sprintf("::ffff:%v/%d", ip.To16(), n))
- got := IpToRadixkey(ip.To16(), n)
- if exp != got {
- t.Fatalf(`exp %v; got %v`, exp, got)
- }
- }
- }
- }
-}
-
-func TestMultipath(t *testing.T) {
- UseMultiplePaths.Enabled = true
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65000})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.150.1")
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- peer1 := &PeerInfo{AS: 1, Address: net.IP{1, 1, 1, 1}, ID: net.IP{1, 1, 1, 1}}
- path1 := ProcessMessage(updateMsg, peer1, time.Now())[0]
- peer2 := &PeerInfo{AS: 2, Address: net.IP{2, 2, 2, 2}, ID: net.IP{2, 2, 2, 2}}
-
- med = bgp.NewPathAttributeMultiExitDisc(100)
- nexthop = bgp.NewPathAttributeNextHop("192.168.150.2")
- pathAttributes = []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
- updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path2 := ProcessMessage(updateMsg, peer2, time.Now())[0]
-
- d := NewDestination(nlri[0], 0)
- d.Calculate(path2)
-
- best, old, multi := d.Calculate(path1).GetChanges(GLOBAL_RIB_NAME, 0, false)
- assert.NotNil(t, best)
- assert.Equal(t, old, path2)
- assert.Equal(t, len(multi), 2)
- assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME, 0)), 2)
-
- path3 := path2.Clone(true)
- dd := d.Calculate(path3)
- best, old, multi = dd.GetChanges(GLOBAL_RIB_NAME, 0, false)
- assert.Nil(t, best)
- assert.Equal(t, old, path1)
- assert.Equal(t, len(multi), 1)
- assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME, 0)), 1)
-
- peer3 := &PeerInfo{AS: 3, Address: net.IP{3, 3, 3, 3}, ID: net.IP{3, 3, 3, 3}}
- med = bgp.NewPathAttributeMultiExitDisc(50)
- nexthop = bgp.NewPathAttributeNextHop("192.168.150.3")
- pathAttributes = []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
- updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path4 := ProcessMessage(updateMsg, peer3, time.Now())[0]
- dd = d.Calculate(path4)
- best, _, multi = dd.GetChanges(GLOBAL_RIB_NAME, 0, false)
- assert.NotNil(t, best)
- assert.Equal(t, len(multi), 1)
- assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME, 0)), 2)
-
- nexthop = bgp.NewPathAttributeNextHop("192.168.150.2")
- pathAttributes = []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
- updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path5 := ProcessMessage(updateMsg, peer2, time.Now())[0]
- best, _, multi = d.Calculate(path5).GetChanges(GLOBAL_RIB_NAME, 0, false)
- assert.NotNil(t, best)
- assert.Equal(t, len(multi), 2)
- assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME, 0)), 3)
-
- UseMultiplePaths.Enabled = false
-}
-
-func TestIdMap(t *testing.T) {
- d := NewDestination(bgp.NewIPAddrPrefix(24, "10.10.0.101"), 64)
- for i := 0; ; i++ {
- if id, err := d.localIdMap.FindandSetZeroBit(); err == nil {
- assert.Equal(t, uint(i+1), id)
- } else {
- assert.Equal(t, i, 63)
- break
- }
- }
- d.localIdMap.Expand()
- for i := 0; i < 64; i++ {
- id, _ := d.localIdMap.FindandSetZeroBit()
- assert.Equal(t, id, uint(64+i))
- }
- _, err := d.localIdMap.FindandSetZeroBit()
- assert.NotNil(t, err)
-}
-
-func TestGetWithdrawnPath(t *testing.T) {
- attrs := []bgp.PathAttributeInterface{
- bgp.NewPathAttributeOrigin(0),
- }
- p1 := NewPath(nil, bgp.NewIPAddrPrefix(24, "13.2.3.0"), false, attrs, time.Now(), false)
- p2 := NewPath(nil, bgp.NewIPAddrPrefix(24, "13.2.4.0"), false, attrs, time.Now(), false)
- p3 := NewPath(nil, bgp.NewIPAddrPrefix(24, "13.2.5.0"), false, attrs, time.Now(), false)
-
- u := &Update{
- KnownPathList: []*Path{p2},
- OldKnownPathList: []*Path{p1, p2, p3},
- }
-
- l := u.GetWithdrawnPath()
- assert.Equal(t, len(l), 2)
- assert.Equal(t, l[0].GetNlri(), p1.GetNlri())
-}
diff --git a/table/message.go b/table/message.go
deleted file mode 100644
index 8b9a4440..00000000
--- a/table/message.go
+++ /dev/null
@@ -1,502 +0,0 @@
-// Copyright (C) 2014 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 (
- "bytes"
- "reflect"
-
- "github.com/osrg/gobgp/packet/bgp"
- log "github.com/sirupsen/logrus"
-)
-
-func UpdatePathAttrs2ByteAs(msg *bgp.BGPUpdate) error {
- ps := msg.PathAttributes
- msg.PathAttributes = make([]bgp.PathAttributeInterface, len(ps))
- copy(msg.PathAttributes, ps)
- var asAttr *bgp.PathAttributeAsPath
- idx := 0
- for i, attr := range msg.PathAttributes {
- if a, ok := attr.(*bgp.PathAttributeAsPath); ok {
- asAttr = a
- idx = i
- break
- }
- }
-
- if asAttr == nil {
- return nil
- }
-
- as4Params := make([]*bgp.As4PathParam, 0, len(asAttr.Value))
- as2Params := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value))
- mkAs4 := false
- for _, param := range asAttr.Value {
- segType := param.GetType()
- asList := param.GetAS()
- as2Path := make([]uint16, 0, len(asList))
- for _, as := range asList {
- if as > (1<<16)-1 {
- mkAs4 = true
- as2Path = append(as2Path, bgp.AS_TRANS)
- } else {
- as2Path = append(as2Path, uint16(as))
- }
- }
- as2Params = append(as2Params, bgp.NewAsPathParam(segType, as2Path))
-
- // RFC 6793 4.2.2 Generating Updates
- //
- // Whenever the AS path information contains the AS_CONFED_SEQUENCE or
- // AS_CONFED_SET path segment, the NEW BGP speaker MUST exclude such
- // path segments from the AS4_PATH attribute being constructed.
- switch segType {
- case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET:
- // pass
- default:
- if as4param, ok := param.(*bgp.As4PathParam); ok {
- as4Params = append(as4Params, as4param)
- }
- }
- }
- msg.PathAttributes[idx] = bgp.NewPathAttributeAsPath(as2Params)
- if mkAs4 {
- msg.PathAttributes = append(msg.PathAttributes, bgp.NewPathAttributeAs4Path(as4Params))
- }
- return nil
-}
-
-func UpdatePathAttrs4ByteAs(msg *bgp.BGPUpdate) error {
- var asAttr *bgp.PathAttributeAsPath
- var as4Attr *bgp.PathAttributeAs4Path
- asAttrPos := 0
- as4AttrPos := 0
- for i, attr := range msg.PathAttributes {
- switch attr.(type) {
- case *bgp.PathAttributeAsPath:
- asAttr = attr.(*bgp.PathAttributeAsPath)
- for j, param := range asAttr.Value {
- as2Param, ok := param.(*bgp.AsPathParam)
- if ok {
- asPath := make([]uint32, 0, len(as2Param.AS))
- for _, as := range as2Param.AS {
- asPath = append(asPath, uint32(as))
- }
- as4Param := bgp.NewAs4PathParam(as2Param.Type, asPath)
- asAttr.Value[j] = as4Param
- }
- }
- asAttrPos = i
- msg.PathAttributes[i] = asAttr
- case *bgp.PathAttributeAs4Path:
- as4AttrPos = i
- as4Attr = attr.(*bgp.PathAttributeAs4Path)
- }
- }
-
- if as4Attr != nil {
- msg.PathAttributes = append(msg.PathAttributes[:as4AttrPos], msg.PathAttributes[as4AttrPos+1:]...)
- }
-
- if asAttr == nil || as4Attr == nil {
- return nil
- }
-
- asLen := 0
- asConfedLen := 0
- asParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value))
- for _, param := range asAttr.Value {
- asLen += param.ASLen()
- switch param.GetType() {
- case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET:
- asConfedLen++
- case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ:
- asConfedLen += len(param.GetAS())
- }
- asParams = append(asParams, param)
- }
-
- as4Len := 0
- as4Params := make([]bgp.AsPathParamInterface, 0, len(as4Attr.Value))
- if as4Attr != nil {
- for _, p := range as4Attr.Value {
- // RFC 6793 6. Error Handling
- //
- // the path segment types AS_CONFED_SEQUENCE and AS_CONFED_SET [RFC5065]
- // MUST NOT be carried in the AS4_PATH attribute of an UPDATE message.
- // A NEW BGP speaker that receives these path segment types in the AS4_PATH
- // attribute of an UPDATE message from an OLD BGP speaker MUST discard
- // these path segments, adjust the relevant attribute fields accordingly,
- // and continue processing the UPDATE message.
- // This case SHOULD be logged locally for analysis.
- switch p.Type {
- case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET:
- typ := "CONFED_SEQ"
- if p.Type == bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET {
- typ = "CONFED_SET"
- }
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Warnf("AS4_PATH contains %s segment %s. ignore", typ, p.String())
- continue
- }
- as4Len += p.ASLen()
- as4Params = append(as4Params, p)
- }
- }
-
- if asLen+asConfedLen < as4Len {
- log.WithFields(log.Fields{
- "Topic": "Table",
- }).Warn("AS4_PATH is longer than AS_PATH. ignore AS4_PATH")
- return nil
- }
-
- keepNum := asLen + asConfedLen - as4Len
-
- newParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value))
- for _, param := range asParams {
- if keepNum-param.ASLen() >= 0 {
- newParams = append(newParams, param)
- keepNum -= param.ASLen()
- } else {
- // only SEQ param reaches here
- newParams = append(newParams, bgp.NewAs4PathParam(param.GetType(), param.GetAS()[:keepNum]))
- keepNum = 0
- }
-
- if keepNum <= 0 {
- break
- }
- }
-
- for _, param := range as4Params {
- lastParam := newParams[len(newParams)-1]
- lastParamAS := lastParam.GetAS()
- paramType := param.GetType()
- paramAS := param.GetAS()
- if paramType == lastParam.GetType() && paramType == bgp.BGP_ASPATH_ATTR_TYPE_SEQ {
- if len(lastParamAS)+len(paramAS) > 255 {
- newParams[len(newParams)-1] = bgp.NewAs4PathParam(paramType, append(lastParamAS, paramAS[:255-len(lastParamAS)]...))
- newParams = append(newParams, bgp.NewAs4PathParam(paramType, paramAS[255-len(lastParamAS):]))
- } else {
- newParams[len(newParams)-1] = bgp.NewAs4PathParam(paramType, append(lastParamAS, paramAS...))
- }
- } else {
- newParams = append(newParams, param)
- }
- }
-
- newIntfParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value))
- newIntfParams = append(newIntfParams, newParams...)
-
- msg.PathAttributes[asAttrPos] = bgp.NewPathAttributeAsPath(newIntfParams)
- return nil
-}
-
-func UpdatePathAggregator2ByteAs(msg *bgp.BGPUpdate) {
- as := uint32(0)
- var addr string
- for i, attr := range msg.PathAttributes {
- switch attr.(type) {
- case *bgp.PathAttributeAggregator:
- agg := attr.(*bgp.PathAttributeAggregator)
- addr = agg.Value.Address.String()
- if agg.Value.AS > (1<<16)-1 {
- as = agg.Value.AS
- msg.PathAttributes[i] = bgp.NewPathAttributeAggregator(uint16(bgp.AS_TRANS), addr)
- } else {
- msg.PathAttributes[i] = bgp.NewPathAttributeAggregator(uint16(agg.Value.AS), addr)
- }
- }
- }
- if as != 0 {
- msg.PathAttributes = append(msg.PathAttributes, bgp.NewPathAttributeAs4Aggregator(as, addr))
- }
-}
-
-func UpdatePathAggregator4ByteAs(msg *bgp.BGPUpdate) error {
- var aggAttr *bgp.PathAttributeAggregator
- var agg4Attr *bgp.PathAttributeAs4Aggregator
- agg4AttrPos := 0
- for i, attr := range msg.PathAttributes {
- switch attr.(type) {
- case *bgp.PathAttributeAggregator:
- attr := attr.(*bgp.PathAttributeAggregator)
- if attr.Value.Askind == reflect.Uint16 {
- aggAttr = attr
- aggAttr.Value.Askind = reflect.Uint32
- }
- case *bgp.PathAttributeAs4Aggregator:
- agg4Attr = attr.(*bgp.PathAttributeAs4Aggregator)
- agg4AttrPos = i
- }
- }
- if aggAttr == nil && agg4Attr == nil {
- return nil
- }
-
- if aggAttr == nil && agg4Attr != nil {
- return bgp.NewMessageError(bgp.BGP_ERROR_UPDATE_MESSAGE_ERROR, bgp.BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "AS4 AGGREGATOR attribute exists, but AGGREGATOR doesn't")
- }
-
- if agg4Attr != nil {
- msg.PathAttributes = append(msg.PathAttributes[:agg4AttrPos], msg.PathAttributes[agg4AttrPos+1:]...)
- aggAttr.Value.AS = agg4Attr.Value.AS
- }
- return nil
-}
-
-type cage struct {
- attrsBytes []byte
- paths []*Path
-}
-
-func newCage(b []byte, path *Path) *cage {
- return &cage{
- attrsBytes: b,
- paths: []*Path{path},
- }
-}
-
-type packerInterface interface {
- add(*Path)
- pack(options ...*bgp.MarshallingOption) []*bgp.BGPMessage
-}
-
-type packer struct {
- eof bool
- family bgp.RouteFamily
- total uint32
-}
-
-type packerMP struct {
- packer
- paths []*Path
- withdrawals []*Path
-}
-
-func (p *packerMP) add(path *Path) {
- p.packer.total++
-
- if path.IsEOR() {
- p.packer.eof = true
- return
- }
-
- if path.IsWithdraw {
- p.withdrawals = append(p.withdrawals, path)
- return
- }
-
- p.paths = append(p.paths, path)
-}
-
-func createMPReachMessage(path *Path) *bgp.BGPMessage {
- oattrs := path.GetPathAttrs()
- attrs := make([]bgp.PathAttributeInterface, 0, len(oattrs))
- for _, a := range oattrs {
- if a.GetType() == bgp.BGP_ATTR_TYPE_MP_REACH_NLRI {
- attrs = append(attrs, bgp.NewPathAttributeMpReachNLRI(path.GetNexthop().String(), []bgp.AddrPrefixInterface{path.GetNlri()}))
- } else {
- attrs = append(attrs, a)
- }
- }
- return bgp.NewBGPUpdateMessage(nil, attrs, nil)
-}
-
-func (p *packerMP) pack(options ...*bgp.MarshallingOption) []*bgp.BGPMessage {
- msgs := make([]*bgp.BGPMessage, 0, p.packer.total)
-
- for _, path := range p.withdrawals {
- nlris := []bgp.AddrPrefixInterface{path.GetNlri()}
- msgs = append(msgs, bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{bgp.NewPathAttributeMpUnreachNLRI(nlris)}, nil))
- }
-
- for _, path := range p.paths {
- msgs = append(msgs, createMPReachMessage(path))
- }
-
- if p.eof {
- msgs = append(msgs, bgp.NewEndOfRib(p.family))
- }
- return msgs
-}
-
-func newPackerMP(f bgp.RouteFamily) *packerMP {
- return &packerMP{
- packer: packer{
- family: f,
- },
- withdrawals: make([]*Path, 0),
- paths: make([]*Path, 0),
- }
-}
-
-type packerV4 struct {
- packer
- hashmap map[uint32][]*cage
- mpPaths []*Path
- withdrawals []*Path
-}
-
-func (p *packerV4) add(path *Path) {
- p.packer.total++
-
- if path.IsEOR() {
- p.packer.eof = true
- return
- }
-
- if path.IsWithdraw {
- p.withdrawals = append(p.withdrawals, path)
- return
- }
-
- if path.GetNexthop().To4() == nil {
- // RFC 5549
- p.mpPaths = append(p.mpPaths, path)
- return
- }
-
- key := path.GetHash()
- attrsB := bytes.NewBuffer(make([]byte, 0))
- for _, v := range path.GetPathAttrs() {
- b, _ := v.Serialize()
- attrsB.Write(b)
- }
-
- if cages, y := p.hashmap[key]; y {
- added := false
- for _, c := range cages {
- if bytes.Equal(c.attrsBytes, attrsB.Bytes()) {
- c.paths = append(c.paths, path)
- added = true
- break
- }
- }
- if !added {
- p.hashmap[key] = append(p.hashmap[key], newCage(attrsB.Bytes(), path))
- }
- } else {
- p.hashmap[key] = []*cage{newCage(attrsB.Bytes(), path)}
- }
-}
-
-func (p *packerV4) pack(options ...*bgp.MarshallingOption) []*bgp.BGPMessage {
- split := func(max int, paths []*Path) ([]*bgp.IPAddrPrefix, []*Path) {
- nlris := make([]*bgp.IPAddrPrefix, 0, max)
- i := 0
- if max > len(paths) {
- max = len(paths)
- }
- for ; i < max; i++ {
- nlris = append(nlris, paths[i].GetNlri().(*bgp.IPAddrPrefix))
- }
- return nlris, paths[i:]
- }
- addpathNLRILen := 0
- if bgp.IsAddPathEnabled(false, p.packer.family, options) {
- addpathNLRILen = 4
- }
- // Header + Update (WithdrawnRoutesLen +
- // TotalPathAttributeLen + attributes + maxlen of NLRI).
- // the max size of NLRI is 5bytes (plus 4bytes with addpath enabled)
- maxNLRIs := func(attrsLen int) int {
- return (bgp.BGP_MAX_MESSAGE_LENGTH - (19 + 2 + 2 + attrsLen)) / (5 + addpathNLRILen)
- }
-
- loop := func(attrsLen int, paths []*Path, cb func([]*bgp.IPAddrPrefix)) {
- max := maxNLRIs(attrsLen)
- var nlris []*bgp.IPAddrPrefix
- for {
- nlris, paths = split(max, paths)
- if len(nlris) == 0 {
- break
- }
- cb(nlris)
- }
- }
-
- msgs := make([]*bgp.BGPMessage, 0, p.packer.total)
-
- loop(0, p.withdrawals, func(nlris []*bgp.IPAddrPrefix) {
- msgs = append(msgs, bgp.NewBGPUpdateMessage(nlris, nil, nil))
- })
-
- for _, cages := range p.hashmap {
- for _, c := range cages {
- paths := c.paths
-
- attrs := paths[0].GetPathAttrs()
- attrsLen := 0
- for _, a := range attrs {
- attrsLen += a.Len()
- }
-
- loop(attrsLen, paths, func(nlris []*bgp.IPAddrPrefix) {
- msgs = append(msgs, bgp.NewBGPUpdateMessage(nil, attrs, nlris))
- })
- }
- }
-
- for _, path := range p.mpPaths {
- msgs = append(msgs, createMPReachMessage(path))
- }
-
- if p.eof {
- msgs = append(msgs, bgp.NewEndOfRib(p.family))
- }
- return msgs
-}
-
-func newPackerV4(f bgp.RouteFamily) *packerV4 {
- return &packerV4{
- packer: packer{
- family: f,
- },
- hashmap: make(map[uint32][]*cage),
- withdrawals: make([]*Path, 0),
- mpPaths: make([]*Path, 0),
- }
-}
-
-func newPacker(f bgp.RouteFamily) packerInterface {
- switch f {
- case bgp.RF_IPv4_UC:
- return newPackerV4(bgp.RF_IPv4_UC)
- default:
- return newPackerMP(f)
- }
-}
-
-func CreateUpdateMsgFromPaths(pathList []*Path, options ...*bgp.MarshallingOption) []*bgp.BGPMessage {
- msgs := make([]*bgp.BGPMessage, 0, len(pathList))
-
- m := make(map[bgp.RouteFamily]packerInterface)
- for _, path := range pathList {
- f := path.GetRouteFamily()
- if _, y := m[f]; !y {
- m[f] = newPacker(f)
- }
- m[f].add(path)
- }
-
- for _, p := range m {
- msgs = append(msgs, p.pack(options...)...)
- }
- return msgs
-}
diff --git a/table/message_test.go b/table/message_test.go
deleted file mode 100644
index 11c8dd19..00000000
--- a/table/message_test.go
+++ /dev/null
@@ -1,663 +0,0 @@
-// Copyright (C) 2014 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"
- "reflect"
- "testing"
- "time"
-
- "github.com/osrg/gobgp/packet/bgp"
- "github.com/stretchr/testify/assert"
-)
-
-// before:
-// as-path : 65000, 4000, 400000, 300000, 40001
-// expected result:
-// as-path : 65000, 4000, 23456, 23456, 40001
-// as4-path : 65000, 4000, 400000, 300000, 40001
-func TestAsPathAs2Trans1(t *testing.T) {
- as := []uint32{65000, 4000, 400000, 300000, 40001}
- params := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as)}
- aspath := bgp.NewPathAttributeAsPath(params)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs2ByteAs(msg)
- assert.Equal(t, len(msg.PathAttributes), 2)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS), 5)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[0], uint16(65000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[1], uint16(4000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[2], uint16(bgp.AS_TRANS))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[3], uint16(bgp.AS_TRANS))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[4], uint16(40001))
- assert.Equal(t, len(msg.PathAttributes[1].(*bgp.PathAttributeAs4Path).Value), 1)
- assert.Equal(t, len(msg.PathAttributes[1].(*bgp.PathAttributeAs4Path).Value[0].AS), 5)
- assert.Equal(t, msg.PathAttributes[1].(*bgp.PathAttributeAs4Path).Value[0].AS[0], uint32(65000))
- assert.Equal(t, msg.PathAttributes[1].(*bgp.PathAttributeAs4Path).Value[0].AS[1], uint32(4000))
- assert.Equal(t, msg.PathAttributes[1].(*bgp.PathAttributeAs4Path).Value[0].AS[2], uint32(400000))
- assert.Equal(t, msg.PathAttributes[1].(*bgp.PathAttributeAs4Path).Value[0].AS[3], uint32(300000))
- assert.Equal(t, msg.PathAttributes[1].(*bgp.PathAttributeAs4Path).Value[0].AS[4], uint32(40001))
-}
-
-// before:
-// as-path : 65000, 4000, 40000, 30000, 40001
-// expected result:
-// as-path : 65000, 4000, 40000, 30000, 40001
-func TestAsPathAs2Trans2(t *testing.T) {
- as := []uint32{65000, 4000, 40000, 30000, 40001}
- params := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as)}
- aspath := bgp.NewPathAttributeAsPath(params)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs2ByteAs(msg)
- assert.Equal(t, len(msg.PathAttributes), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS), 5)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[0], uint16(65000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[1], uint16(4000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[2], uint16(40000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[3], uint16(30000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.AsPathParam).AS[4], uint16(40001))
-}
-
-// before:
-// as-path : 65000, 4000, 23456, 23456, 40001
-// as4-path : 400000, 300000, 40001
-// expected result:
-// as-path : 65000, 4000, 400000, 300000, 40001
-func TestAsPathAs4Trans1(t *testing.T) {
- as := []uint16{65000, 4000, bgp.AS_TRANS, bgp.AS_TRANS, 40001}
- params := []bgp.AsPathParamInterface{bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as)}
- aspath := bgp.NewPathAttributeAsPath(params)
-
- as4 := []uint32{400000, 300000, 40001}
- param4s := []*bgp.As4PathParam{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as4)}
- as4path := bgp.NewPathAttributeAs4Path(param4s)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath, as4path}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(msg)
- assert.Equal(t, len(msg.PathAttributes), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS), 5)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[0], uint32(65000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[1], uint32(4000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[2], uint32(400000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[3], uint32(300000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[4], uint32(40001))
-}
-
-// before:
-// as-path : 65000, 4000, {10, 20, 30}, 23456, 23456, 40001
-// as4-path : 400000, 300000, 40001
-// expected result:
-// as-path : 65000, 4000, {10, 20, 30}, 400000, 300000, 40001
-func TestAsPathAs4Trans2(t *testing.T) {
- as1 := []uint16{65000, 4000}
- param1 := bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as1)
- as2 := []uint16{10, 20, 30}
- param2 := bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SET, as2)
- as3 := []uint16{bgp.AS_TRANS, bgp.AS_TRANS, 40001}
- param3 := bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as3)
- params := []bgp.AsPathParamInterface{param1, param2, param3}
- aspath := bgp.NewPathAttributeAsPath(params)
-
- as4 := []uint32{400000, 300000, 40001}
- param4s := []*bgp.As4PathParam{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as4)}
- as4path := bgp.NewPathAttributeAs4Path(param4s)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath, as4path}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(msg)
- assert.Equal(t, len(msg.PathAttributes), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 3)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS), 2)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[0], uint32(65000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[1], uint32(4000))
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS), 3)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS[0], uint32(10))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS[1], uint32(20))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS[2], uint32(30))
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[2].(*bgp.As4PathParam).AS), 3)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[2].(*bgp.As4PathParam).AS[0], uint32(400000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[2].(*bgp.As4PathParam).AS[1], uint32(300000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[2].(*bgp.As4PathParam).AS[2], uint32(40001))
-}
-
-// before:
-// as-path : 65000, 4000, {10, 20, 30}, 23456, 23456, 40001
-// as4-path : 3000, 400000, 300000, 40001
-// expected result:
-// as-path : 65000, 4000, 3000, 400000, 300000, 40001
-func TestAsPathAs4Trans3(t *testing.T) {
- as1 := []uint16{65000, 4000}
- param1 := bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as1)
- as2 := []uint16{10, 20, 30}
- param2 := bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SET, as2)
- as3 := []uint16{bgp.AS_TRANS, bgp.AS_TRANS, 40001}
- param3 := bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as3)
- params := []bgp.AsPathParamInterface{param1, param2, param3}
- aspath := bgp.NewPathAttributeAsPath(params)
-
- as4 := []uint32{3000, 400000, 300000, 40001}
- param4s := []*bgp.As4PathParam{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as4)}
- as4path := bgp.NewPathAttributeAs4Path(param4s)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath, as4path}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(msg)
- assert.Equal(t, len(msg.PathAttributes), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS), 6)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[0], uint32(65000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[1], uint32(4000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[2], uint32(3000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[3], uint32(400000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[4], uint32(300000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[5], uint32(40001))
-}
-
-// before:
-// as-path : 65000, 4000, 23456, 23456, 40001
-// as4-path : 400000, 300000, 40001, {10, 20, 30}
-// expected result:
-// as-path : 65000, 400000, 300000, 40001, {10, 20, 30}
-func TestAsPathAs4Trans4(t *testing.T) {
- as := []uint16{65000, 4000, bgp.AS_TRANS, bgp.AS_TRANS, 40001}
- params := []bgp.AsPathParamInterface{bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as)}
- aspath := bgp.NewPathAttributeAsPath(params)
-
- as4 := []uint32{400000, 300000, 40001}
- as4param1 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as4)
- as5 := []uint32{10, 20, 30}
- as4param2 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SET, as5)
- param4s := []*bgp.As4PathParam{as4param1, as4param2}
- as4path := bgp.NewPathAttributeAs4Path(param4s)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath, as4path}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(msg)
- assert.Equal(t, len(msg.PathAttributes), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 2)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS), 4)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[0], uint32(65000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[1], uint32(400000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[2], uint32(300000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[3], uint32(40001))
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS), 3)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS[0], uint32(10))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS[1], uint32(20))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS[2], uint32(30))
-}
-
-// before:
-// as-path : 65000, 4000, 23456, 23456, 40001
-// as4-path : {10, 20, 30} 400000, 300000, 40001
-// expected result:
-// as-path : 65000, {10, 20, 30}, 400000, 300000, 40001
-func TestAsPathAs4Trans5(t *testing.T) {
- as := []uint16{65000, 4000, bgp.AS_TRANS, bgp.AS_TRANS, 40001}
- params := []bgp.AsPathParamInterface{bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as)}
- aspath := bgp.NewPathAttributeAsPath(params)
-
- as4 := []uint32{400000, 300000, 40001}
- as4param1 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as4)
- as5 := []uint32{10, 20, 30}
- as4param2 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SET, as5)
- param4s := []*bgp.As4PathParam{as4param2, as4param1}
- as4path := bgp.NewPathAttributeAs4Path(param4s)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath, as4path}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(msg)
- assert.Equal(t, len(msg.PathAttributes), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 3)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS), 1)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[0], uint32(65000))
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS), 3)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS[0], uint32(10))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS[1], uint32(20))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[1].(*bgp.As4PathParam).AS[2], uint32(30))
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[2].(*bgp.As4PathParam).AS), 3)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[2].(*bgp.As4PathParam).AS[0], uint32(400000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[2].(*bgp.As4PathParam).AS[1], uint32(300000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[2].(*bgp.As4PathParam).AS[2], uint32(40001))
-}
-
-// before:
-// as-path : 65000, 4000, 23456, 23456, 40001
-// as4-path : 100000, 65000, 4000, 400000, 300000, 40001
-// expected result:
-// as-path : 65000, 4000, 23456, 23456, 40001
-func TestAsPathAs4TransInvalid1(t *testing.T) {
- as := []uint16{65000, 4000, bgp.AS_TRANS, bgp.AS_TRANS, 40001}
- params := []bgp.AsPathParamInterface{bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as)}
- aspath := bgp.NewPathAttributeAsPath(params)
-
- as4 := []uint32{100000, 65000, 4000, 400000, 300000, 40001}
- as4param1 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as4)
- param4s := []*bgp.As4PathParam{as4param1}
- as4path := bgp.NewPathAttributeAs4Path(param4s)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath, as4path}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(msg)
- assert.Equal(t, len(msg.PathAttributes), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS), 5)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[0], uint32(65000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[1], uint32(4000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[2], uint32(bgp.AS_TRANS))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[3], uint32(bgp.AS_TRANS))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[4], uint32(40001))
-}
-
-// before:
-// as-path : 65000, 4000, 23456, 23456, 40001
-// as4-path : 300000, 40001
-// expected result:
-// as-path : 65000, 4000, 23456, 300000, 40001
-func TestAsPathAs4TransInvalid2(t *testing.T) {
- as := []uint16{65000, 4000, bgp.AS_TRANS, bgp.AS_TRANS, 40001}
- params := []bgp.AsPathParamInterface{bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as)}
- aspath := bgp.NewPathAttributeAsPath(params)
-
- as4 := []uint32{300000, 40001}
- as4param1 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as4)
- param4s := []*bgp.As4PathParam{as4param1}
- as4path := bgp.NewPathAttributeAs4Path(param4s)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath, as4path}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(msg)
- assert.Equal(t, len(msg.PathAttributes), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS), 5)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[0], uint32(65000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[1], uint32(4000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[2], uint32(bgp.AS_TRANS))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[3], uint32(300000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[4], uint32(40001))
-}
-
-// before:
-// as-path : 65000, 4000, 23456, 23456, 40001
-// as4-path : nil
-// expected result:
-// as-path : 65000, 4000, 23456, 23456, 40001
-func TestAsPathAs4TransInvalid3(t *testing.T) {
- as := []uint16{65000, 4000, bgp.AS_TRANS, bgp.AS_TRANS, 40001}
- params := []bgp.AsPathParamInterface{bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as)}
- aspath := bgp.NewPathAttributeAsPath(params)
-
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(msg)
- assert.Equal(t, len(msg.PathAttributes), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS), 5)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[0], uint32(65000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[1], uint32(4000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[2], uint32(bgp.AS_TRANS))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[3], uint32(bgp.AS_TRANS))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[4], uint32(40001))
-}
-
-// before:
-// as-path : 65000, 4000, 23456, 23456, 40001
-// as4-path : empty
-// expected result:
-// as-path : 65000, 4000, 23456, 23456, 40001
-func TestAsPathAs4TransInvalid4(t *testing.T) {
- as := []uint16{65000, 4000, bgp.AS_TRANS, bgp.AS_TRANS, 40001}
- params := []bgp.AsPathParamInterface{bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as)}
- aspath := bgp.NewPathAttributeAsPath(params)
-
- as4 := []uint32{}
- as4param1 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as4)
- param4s := []*bgp.As4PathParam{as4param1}
- as4path := bgp.NewPathAttributeAs4Path(param4s)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath, as4path}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(msg)
- assert.Equal(t, len(msg.PathAttributes), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value), 1)
- assert.Equal(t, len(msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS), 5)
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[0], uint32(65000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[1], uint32(4000))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[2], uint32(bgp.AS_TRANS))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[3], uint32(bgp.AS_TRANS))
- assert.Equal(t, msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value[0].(*bgp.As4PathParam).AS[4], uint32(40001))
-}
-
-func TestASPathAs4TransMultipleParams(t *testing.T) {
- as1 := []uint16{17676, 2914, 174, 50607}
- as2 := []uint16{bgp.AS_TRANS, bgp.AS_TRANS}
- params := []bgp.AsPathParamInterface{bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as1), bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as2)}
- aspath := bgp.NewPathAttributeAsPath(params)
-
- as41 := []uint32{2914, 174, 50607}
- as42 := []uint32{198035, 198035}
- as4param1 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as41)
- as4param2 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as42)
- param4s := []*bgp.As4PathParam{as4param1, as4param2}
- as4path := bgp.NewPathAttributeAs4Path(param4s)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath, as4path}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(msg)
- for _, param := range msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value {
- p := param.(*bgp.As4PathParam)
- assert.Equal(t, p.Num, uint8(len(p.AS)))
- }
-}
-
-func TestASPathAs4TransMultipleLargeParams(t *testing.T) {
- as1 := make([]uint16, 0, 255)
- for i := 0; i < 255-5; i++ {
- as1 = append(as1, uint16(i+1))
- }
- as1 = append(as1, []uint16{17676, 2914, 174, 50607}...)
- as2 := []uint16{bgp.AS_TRANS, bgp.AS_TRANS}
- params := []bgp.AsPathParamInterface{bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as1), bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as2)}
- aspath := bgp.NewPathAttributeAsPath(params)
-
- as41 := []uint32{2914, 174, 50607}
- as42 := []uint32{198035, 198035}
- as4param1 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as41)
- as4param2 := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, as42)
- param4s := []*bgp.As4PathParam{as4param1, as4param2}
- as4path := bgp.NewPathAttributeAs4Path(param4s)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{aspath, as4path}, nil).Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(msg)
- for _, param := range msg.PathAttributes[0].(*bgp.PathAttributeAsPath).Value {
- p := param.(*bgp.As4PathParam)
- assert.Equal(t, p.Num, uint8(len(p.AS)))
- }
-}
-
-func TestAggregator4BytesASes(t *testing.T) {
- getAggr := func(msg *bgp.BGPUpdate) *bgp.PathAttributeAggregator {
- for _, attr := range msg.PathAttributes {
- switch attr.(type) {
- case *bgp.PathAttributeAggregator:
- return attr.(*bgp.PathAttributeAggregator)
- }
- }
- return nil
- }
-
- getAggr4 := func(msg *bgp.BGPUpdate) *bgp.PathAttributeAs4Aggregator {
- for _, attr := range msg.PathAttributes {
- switch attr.(type) {
- case *bgp.PathAttributeAs4Aggregator:
- return attr.(*bgp.PathAttributeAs4Aggregator)
- }
- }
- return nil
- }
-
- addr := "192.168.0.1"
- as4 := uint32(100000)
- as := uint32(1000)
- msg := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{bgp.NewPathAttributeAggregator(as4, addr)}, nil).Body.(*bgp.BGPUpdate)
-
- // 4byte capable to 4byte capable for 4 bytes AS
- assert.Equal(t, UpdatePathAggregator4ByteAs(msg), nil)
- assert.Equal(t, getAggr(msg).Value.AS, as4)
- assert.Equal(t, getAggr(msg).Value.Address.String(), addr)
-
- // 4byte capable to 2byte capable for 4 bytes AS
- UpdatePathAggregator2ByteAs(msg)
- assert.Equal(t, getAggr(msg).Value.AS, uint32(bgp.AS_TRANS))
- assert.Equal(t, getAggr(msg).Value.Askind, reflect.Uint16)
- assert.Equal(t, getAggr4(msg).Value.AS, as4)
- assert.Equal(t, getAggr4(msg).Value.Address.String(), addr)
-
- msg = bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{bgp.NewPathAttributeAggregator(uint16(bgp.AS_TRANS), addr), bgp.NewPathAttributeAs4Aggregator(as4, addr)}, nil).Body.(*bgp.BGPUpdate)
- assert.Equal(t, getAggr(msg).Value.AS, uint32(bgp.AS_TRANS))
- assert.Equal(t, getAggr(msg).Value.Askind, reflect.Uint16)
-
- // non 4byte capable to 4byte capable for 4 bytes AS
- assert.Equal(t, UpdatePathAggregator4ByteAs(msg), nil)
- assert.Equal(t, getAggr(msg).Value.AS, as4)
- assert.Equal(t, getAggr(msg).Value.Askind, reflect.Uint32)
- assert.Equal(t, getAggr(msg).Value.Address.String(), addr)
- assert.Equal(t, getAggr4(msg), (*bgp.PathAttributeAs4Aggregator)(nil))
-
- // non 4byte capable to non 4byte capable for 4 bytes AS
- UpdatePathAggregator2ByteAs(msg)
- assert.Equal(t, getAggr(msg).Value.AS, uint32(bgp.AS_TRANS))
- assert.Equal(t, getAggr(msg).Value.Askind, reflect.Uint16)
- assert.Equal(t, getAggr4(msg).Value.AS, as4)
- assert.Equal(t, getAggr4(msg).Value.Address.String(), addr)
-
- msg = bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{bgp.NewPathAttributeAggregator(uint32(as), addr)}, nil).Body.(*bgp.BGPUpdate)
- // 4byte capable to 4byte capable for 2 bytes AS
- assert.Equal(t, getAggr(msg).Value.AS, as)
- assert.Equal(t, getAggr(msg).Value.Askind, reflect.Uint32)
- assert.Equal(t, UpdatePathAggregator4ByteAs(msg), nil)
- assert.Equal(t, getAggr(msg).Value.AS, as)
- assert.Equal(t, getAggr(msg).Value.Askind, reflect.Uint32)
-
- // 4byte capable to non 4byte capable for 2 bytes AS
- UpdatePathAggregator2ByteAs(msg)
- assert.Equal(t, getAggr4(msg), (*bgp.PathAttributeAs4Aggregator)(nil))
- assert.Equal(t, getAggr(msg).Value.Askind, reflect.Uint16)
- assert.Equal(t, getAggr(msg).Value.AS, as)
-
- msg = bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{bgp.NewPathAttributeAggregator(uint16(as), addr)}, nil).Body.(*bgp.BGPUpdate)
- // non 4byte capable to 4byte capable for 2 bytes AS
- assert.Equal(t, getAggr(msg).Value.AS, as)
- assert.Equal(t, getAggr(msg).Value.Askind, reflect.Uint16)
- assert.Equal(t, UpdatePathAggregator4ByteAs(msg), nil)
-
- assert.Equal(t, getAggr(msg).Value.AS, as)
- assert.Equal(t, getAggr(msg).Value.Askind, reflect.Uint32)
-
- // non 4byte capable to non 4byte capable for 2 bytes AS
- UpdatePathAggregator2ByteAs(msg)
- assert.Equal(t, getAggr(msg).Value.AS, as)
- assert.Equal(t, getAggr(msg).Value.Askind, reflect.Uint16)
- assert.Equal(t, getAggr4(msg), (*bgp.PathAttributeAs4Aggregator)(nil))
-}
-
-func TestBMP(t *testing.T) {
- aspath1 := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{1000000}),
- bgp.NewAs4PathParam(1, []uint32{1000001, 1002}),
- bgp.NewAs4PathParam(2, []uint32{1003, 100004}),
- }
- mp_nlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(100,
- "fe80:1234:1234:5667:8967:af12:8912:1023")}
-
- p := []bgp.PathAttributeInterface{
- bgp.NewPathAttributeOrigin(3),
- bgp.NewPathAttributeAsPath(aspath1),
- bgp.NewPathAttributeMpUnreachNLRI(mp_nlri),
- }
- w := []*bgp.IPAddrPrefix{}
- n := []*bgp.IPAddrPrefix{}
-
- msg := bgp.NewBGPUpdateMessage(w, p, n)
- pList := ProcessMessage(msg, peerR1(), time.Now())
- CreateUpdateMsgFromPaths(pList)
-}
-
-func unreachIndex(msgs []*bgp.BGPMessage) int {
- for i, _ := range msgs {
- for _, a := range msgs[i].Body.(*bgp.BGPUpdate).PathAttributes {
- if a.GetType() == bgp.BGP_ATTR_TYPE_MP_UNREACH_NLRI {
- return i
- }
- }
- }
- // should not be here
- return -1
-}
-
-func TestMixedMPReachMPUnreach(t *testing.T) {
- aspath1 := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{100}),
- }
- nlri1 := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(32, "2222::")}
- nlri2 := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(32, "1111::")}
-
- p := []bgp.PathAttributeInterface{
- bgp.NewPathAttributeOrigin(0),
- bgp.NewPathAttributeAsPath(aspath1),
- bgp.NewPathAttributeMpReachNLRI("1::1", nlri1),
- bgp.NewPathAttributeMpUnreachNLRI(nlri2),
- }
- msg := bgp.NewBGPUpdateMessage(nil, p, nil)
- pList := ProcessMessage(msg, peerR1(), time.Now())
- assert.Equal(t, len(pList), 2)
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.Equal(t, pList[1].IsWithdraw, true)
- msgs := CreateUpdateMsgFromPaths(pList)
- assert.Equal(t, len(msgs), 2)
-
- uIndex := unreachIndex(msgs)
- rIndex := 0
- if uIndex == 0 {
- rIndex = 1
- }
- assert.Equal(t, len(msgs[uIndex].Body.(*bgp.BGPUpdate).PathAttributes), 1)
- assert.Equal(t, len(msgs[rIndex].Body.(*bgp.BGPUpdate).PathAttributes), 3)
-}
-
-func TestMixedNLRIAndMPUnreach(t *testing.T) {
- aspath1 := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{100}),
- }
- nlri1 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.0.0.0")}
- nlri2 := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(32, "1111::")}
-
- p := []bgp.PathAttributeInterface{
- bgp.NewPathAttributeOrigin(0),
- bgp.NewPathAttributeAsPath(aspath1),
- bgp.NewPathAttributeNextHop("1.1.1.1"),
- bgp.NewPathAttributeMpUnreachNLRI(nlri2),
- }
- msg := bgp.NewBGPUpdateMessage(nil, p, nlri1)
- pList := ProcessMessage(msg, peerR1(), time.Now())
-
- assert.Equal(t, len(pList), 2)
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.Equal(t, pList[1].IsWithdraw, true)
- msgs := CreateUpdateMsgFromPaths(pList)
- assert.Equal(t, len(msgs), 2)
-
- uIndex := unreachIndex(msgs)
- rIndex := 0
- if uIndex == 0 {
- rIndex = 1
- }
- assert.Equal(t, len(msgs[uIndex].Body.(*bgp.BGPUpdate).PathAttributes), 1)
- assert.Equal(t, len(msgs[rIndex].Body.(*bgp.BGPUpdate).PathAttributes), 3)
-}
-
-func TestMergeV4NLRIs(t *testing.T) {
- aspath1 := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{100}),
- }
- attrs := []bgp.PathAttributeInterface{
- bgp.NewPathAttributeOrigin(0),
- bgp.NewPathAttributeAsPath(aspath1),
- bgp.NewPathAttributeNextHop("1.1.1.1"),
- }
-
- nr := 1024
- paths := make([]*Path, 0, nr)
- addrs := make([]string, 0, nr)
- for i := 0; i < nr; i++ {
- addrs = append(addrs, fmt.Sprintf("1.1.%d.%d", i>>8&0xff, i&0xff))
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(32, addrs[i])}
- msg := bgp.NewBGPUpdateMessage(nil, attrs, nlri)
- paths = append(paths, ProcessMessage(msg, peerR1(), time.Now())...)
- }
- msgs := CreateUpdateMsgFromPaths(paths)
- assert.Equal(t, len(msgs), 2)
-
- l := make([]*bgp.IPAddrPrefix, 0, nr)
- for _, msg := range msgs {
- u := msg.Body.(*bgp.BGPUpdate)
- assert.Equal(t, len(u.PathAttributes), 3)
- l = append(l, u.NLRI...)
- }
-
- assert.Equal(t, len(l), nr)
- for i, addr := range addrs {
- assert.Equal(t, addr, l[i].Prefix.String())
- }
- for _, msg := range msgs {
- d, _ := msg.Serialize()
- assert.True(t, len(d) < bgp.BGP_MAX_MESSAGE_LENGTH)
- }
-}
-
-func TestNotMergeV4NLRIs(t *testing.T) {
- paths := make([]*Path, 0, 2)
-
- aspath1 := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{100}),
- }
- attrs1 := []bgp.PathAttributeInterface{
- bgp.NewPathAttributeOrigin(0),
- bgp.NewPathAttributeAsPath(aspath1),
- bgp.NewPathAttributeNextHop("1.1.1.1"),
- }
- nlri1 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(32, "1.1.1.1")}
- paths = append(paths, ProcessMessage(bgp.NewBGPUpdateMessage(nil, attrs1, nlri1), peerR1(), time.Now())...)
-
- attrs2 := []bgp.PathAttributeInterface{
- bgp.NewPathAttributeOrigin(0),
- bgp.NewPathAttributeAsPath(aspath1),
- bgp.NewPathAttributeNextHop("2.2.2.2"),
- }
- nlri2 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(32, "2.2.2.2")}
- paths = append(paths, ProcessMessage(bgp.NewBGPUpdateMessage(nil, attrs2, nlri2), peerR1(), time.Now())...)
-
- assert.NotEmpty(t, paths[0].GetHash(), paths[1].GetHash())
-
- msgs := CreateUpdateMsgFromPaths(paths)
- assert.Equal(t, len(msgs), 2)
-
- paths[1].SetHash(paths[0].GetHash())
- msgs = CreateUpdateMsgFromPaths(paths)
- assert.Equal(t, len(msgs), 2)
-}
-
-func TestMergeV4Withdraw(t *testing.T) {
- nr := 1024
- paths := make([]*Path, 0, nr)
- addrs := make([]string, 0, nr)
- for i := 0; i < nr; i++ {
- addrs = append(addrs, fmt.Sprintf("1.1.%d.%d", i>>8&0xff, i&0xff))
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(32, addrs[i])}
- // use different attribute for each nlri
- aspath1 := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{uint32(i)}),
- }
- attrs := []bgp.PathAttributeInterface{
- bgp.NewPathAttributeOrigin(0),
- bgp.NewPathAttributeAsPath(aspath1),
- bgp.NewPathAttributeNextHop("1.1.1.1"),
- }
- msg := bgp.NewBGPUpdateMessage(nlri, attrs, nil)
- paths = append(paths, ProcessMessage(msg, peerR1(), time.Now())...)
- }
- msgs := CreateUpdateMsgFromPaths(paths)
- assert.Equal(t, len(msgs), 2)
-
- l := make([]*bgp.IPAddrPrefix, 0, nr)
- for _, msg := range msgs {
- u := msg.Body.(*bgp.BGPUpdate)
- assert.Equal(t, len(u.PathAttributes), 0)
- l = append(l, u.WithdrawnRoutes...)
- }
- assert.Equal(t, len(l), nr)
- for i, addr := range addrs {
- assert.Equal(t, addr, l[i].Prefix.String())
- }
-
- for _, msg := range msgs {
- d, _ := msg.Serialize()
- assert.True(t, len(d) < bgp.BGP_MAX_MESSAGE_LENGTH)
- }
-}
diff --git a/table/path.go b/table/path.go
deleted file mode 100644
index 1cb81a91..00000000
--- a/table/path.go
+++ /dev/null
@@ -1,1179 +0,0 @@
-// Copyright (C) 2014 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 (
- "bytes"
- "encoding/json"
- "fmt"
- "math"
- "net"
- "sort"
- "time"
-
- log "github.com/sirupsen/logrus"
-
- "github.com/osrg/gobgp/config"
- "github.com/osrg/gobgp/packet/bgp"
-)
-
-const (
- DEFAULT_LOCAL_PREF = 100
-)
-
-type Bitmap struct {
- bitmap []uint64
-}
-
-func (b *Bitmap) Flag(i uint) {
- b.bitmap[i/64] |= 1 << uint(i%64)
-}
-
-func (b *Bitmap) Unflag(i uint) {
- b.bitmap[i/64] &^= 1 << uint(i%64)
-}
-
-func (b *Bitmap) GetFlag(i uint) bool {
- return b.bitmap[i/64]&(1<<uint(i%64)) > 0
-}
-
-func (b *Bitmap) FindandSetZeroBit() (uint, error) {
- for i := 0; i < len(b.bitmap); i++ {
- if b.bitmap[i] == math.MaxUint64 {
- continue
- }
- // replace this with TrailingZero64() when gobgp drops go 1.8 support.
- for j := 0; j < 64; j++ {
- v := ^b.bitmap[i]
- if v&(1<<uint64(j)) > 0 {
- r := i*64 + j
- b.Flag(uint(r))
- return uint(r), nil
- }
- }
- }
- return 0, fmt.Errorf("no space")
-}
-
-func (b *Bitmap) Expand() {
- old := b.bitmap
- new := make([]uint64, len(old)+1)
- for i := 0; i < len(old); i++ {
- new[i] = old[i]
- }
- b.bitmap = new
-}
-
-func NewBitmap(size int) *Bitmap {
- b := &Bitmap{}
- if size != 0 {
- b.bitmap = make([]uint64, (size+64-1)/64)
- }
- return b
-}
-
-type originInfo struct {
- nlri bgp.AddrPrefixInterface
- source *PeerInfo
- timestamp int64
- validation *Validation
- noImplicitWithdraw bool
- isFromExternal bool
- eor bool
- stale bool
-}
-
-type RpkiValidationReasonType string
-
-const (
- RPKI_VALIDATION_REASON_TYPE_NONE RpkiValidationReasonType = "none"
- RPKI_VALIDATION_REASON_TYPE_AS RpkiValidationReasonType = "as"
- RPKI_VALIDATION_REASON_TYPE_LENGTH RpkiValidationReasonType = "length"
-)
-
-var RpkiValidationReasonTypeToIntMap = map[RpkiValidationReasonType]int{
- RPKI_VALIDATION_REASON_TYPE_NONE: 0,
- RPKI_VALIDATION_REASON_TYPE_AS: 1,
- RPKI_VALIDATION_REASON_TYPE_LENGTH: 2,
-}
-
-func (v RpkiValidationReasonType) ToInt() int {
- i, ok := RpkiValidationReasonTypeToIntMap[v]
- if !ok {
- return -1
- }
- return i
-}
-
-var IntToRpkiValidationReasonTypeMap = map[int]RpkiValidationReasonType{
- 0: RPKI_VALIDATION_REASON_TYPE_NONE,
- 1: RPKI_VALIDATION_REASON_TYPE_AS,
- 2: RPKI_VALIDATION_REASON_TYPE_LENGTH,
-}
-
-type Validation struct {
- Status config.RpkiValidationResultType
- Reason RpkiValidationReasonType
- Matched []*ROA
- UnmatchedAs []*ROA
- UnmatchedLength []*ROA
-}
-
-type Path struct {
- info *originInfo
- parent *Path
- pathAttrs []bgp.PathAttributeInterface
- dels []bgp.BGPAttrType
- attrsHash uint32
- aslooped bool
- reason BestPathReason
-
- // For BGP Nexthop Tracking, this field shows if nexthop is invalidated by IGP.
- IsNexthopInvalid bool
- IsWithdraw bool
-}
-
-func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pattrs []bgp.PathAttributeInterface, timestamp time.Time, noImplicitWithdraw bool) *Path {
- if !isWithdraw && pattrs == nil {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Key": nlri.String(),
- }).Error("Need to provide path attributes for non-withdrawn path.")
- return nil
- }
-
- return &Path{
- info: &originInfo{
- nlri: nlri,
- source: source,
- timestamp: timestamp.Unix(),
- noImplicitWithdraw: noImplicitWithdraw,
- },
- IsWithdraw: isWithdraw,
- pathAttrs: pattrs,
- }
-}
-
-func NewEOR(family bgp.RouteFamily) *Path {
- afi, safi := bgp.RouteFamilyToAfiSafi(family)
- nlri, _ := bgp.NewPrefixFromRouteFamily(afi, safi)
- return &Path{
- info: &originInfo{
- nlri: nlri,
- eor: true,
- },
- }
-}
-
-func (path *Path) IsEOR() bool {
- if path.info != nil && path.info.eor {
- return true
- }
- return false
-}
-
-func cloneAsPath(asAttr *bgp.PathAttributeAsPath) *bgp.PathAttributeAsPath {
- newASparams := make([]bgp.AsPathParamInterface, len(asAttr.Value))
- for i, param := range asAttr.Value {
- asList := param.GetAS()
- as := make([]uint32, len(asList))
- copy(as, asList)
- newASparams[i] = bgp.NewAs4PathParam(param.GetType(), as)
- }
- return bgp.NewPathAttributeAsPath(newASparams)
-}
-
-func UpdatePathAttrs(global *config.Global, peer *config.Neighbor, info *PeerInfo, original *Path) *Path {
- if peer.RouteServer.Config.RouteServerClient {
- return original
- }
- path := original.Clone(original.IsWithdraw)
-
- for _, a := range path.GetPathAttrs() {
- if _, y := bgp.PathAttrFlags[a.GetType()]; !y {
- if a.GetFlags()&bgp.BGP_ATTR_FLAG_TRANSITIVE == 0 {
- path.delPathAttr(a.GetType())
- }
- } else {
- switch a.GetType() {
- case bgp.BGP_ATTR_TYPE_CLUSTER_LIST, bgp.BGP_ATTR_TYPE_ORIGINATOR_ID:
- if !(peer.State.PeerType == config.PEER_TYPE_INTERNAL && peer.RouteReflector.Config.RouteReflectorClient) {
- // send these attributes to only rr clients
- path.delPathAttr(a.GetType())
- }
- }
- }
- }
-
- localAddress := info.LocalAddress
- nexthop := path.GetNexthop()
- if peer.State.PeerType == config.PEER_TYPE_EXTERNAL {
- // NEXTHOP handling
- if !path.IsLocal() || nexthop.IsUnspecified() {
- path.SetNexthop(localAddress)
- }
-
- // remove-private-as handling
- path.RemovePrivateAS(peer.Config.LocalAs, peer.State.RemovePrivateAs)
-
- // AS_PATH handling
- confed := peer.IsConfederationMember(global)
- path.PrependAsn(peer.Config.LocalAs, 1, confed)
- if !confed {
- path.removeConfedAs()
- }
-
- // MED Handling
- if med := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC); med != nil && !path.IsLocal() {
- path.delPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- }
-
- } else if peer.State.PeerType == config.PEER_TYPE_INTERNAL {
- // NEXTHOP handling for iBGP
- // if the path generated locally set local address as nexthop.
- // if not, don't modify it.
- // TODO: NEXT-HOP-SELF support
- if path.IsLocal() && nexthop.IsUnspecified() {
- path.SetNexthop(localAddress)
- }
-
- // AS_PATH handling for iBGP
- // if the path has AS_PATH path attribute, don't modify it.
- // if not, attach *empty* AS_PATH path attribute.
- if nh := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH); nh == nil {
- path.PrependAsn(0, 0, false)
- }
-
- // For iBGP peers we are required to send local-pref attribute
- // for connected or local prefixes.
- // We set default local-pref 100.
- if pref := path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF); pref == nil {
- path.setPathAttr(bgp.NewPathAttributeLocalPref(DEFAULT_LOCAL_PREF))
- }
-
- // RFC4456: BGP Route Reflection
- // 8. Avoiding Routing Information Loops
- info := path.GetSource()
- if peer.RouteReflector.Config.RouteReflectorClient {
- // This attribute will carry the BGP Identifier of the originator of the route in the local AS.
- // A BGP speaker SHOULD NOT create an ORIGINATOR_ID attribute if one already exists.
- //
- // RFC4684 3.2 Intra-AS VPN Route Distribution
- // When advertising RT membership NLRI to a route-reflector client,
- // the Originator attribute shall be set to the router-id of the
- // advertiser, and the Next-hop attribute shall be set of the local
- // address for that session.
- if path.GetRouteFamily() == bgp.RF_RTC_UC {
- path.SetNexthop(localAddress)
- path.setPathAttr(bgp.NewPathAttributeOriginatorId(info.LocalID.String()))
- } else if path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGINATOR_ID) == nil {
- if path.IsLocal() {
- path.setPathAttr(bgp.NewPathAttributeOriginatorId(global.Config.RouterId))
- } else {
- path.setPathAttr(bgp.NewPathAttributeOriginatorId(info.ID.String()))
- }
- }
- // When an RR reflects a route, it MUST prepend the local CLUSTER_ID to the CLUSTER_LIST.
- // If the CLUSTER_LIST is empty, it MUST create a new one.
- clusterID := string(peer.RouteReflector.State.RouteReflectorClusterId)
- if p := path.getPathAttr(bgp.BGP_ATTR_TYPE_CLUSTER_LIST); p == nil {
- path.setPathAttr(bgp.NewPathAttributeClusterList([]string{clusterID}))
- } else {
- clusterList := p.(*bgp.PathAttributeClusterList)
- newClusterList := make([]string, 0, len(clusterList.Value))
- for _, ip := range clusterList.Value {
- newClusterList = append(newClusterList, ip.String())
- }
- path.setPathAttr(bgp.NewPathAttributeClusterList(append([]string{clusterID}, newClusterList...)))
- }
- }
-
- } else {
- log.WithFields(log.Fields{
- "Topic": "Peer",
- "Key": peer.State.NeighborAddress,
- }).Warnf("invalid peer type: %d", peer.State.PeerType)
- }
- return path
-}
-
-func (path *Path) GetTimestamp() time.Time {
- return time.Unix(path.OriginInfo().timestamp, 0)
-}
-
-func (path *Path) setTimestamp(t time.Time) {
- path.OriginInfo().timestamp = t.Unix()
-}
-
-func (path *Path) IsLocal() bool {
- return path.GetSource().Address == nil
-}
-
-func (path *Path) IsIBGP() bool {
- return path.GetSource().AS == path.GetSource().LocalAS
-}
-
-// create new PathAttributes
-func (path *Path) Clone(isWithdraw bool) *Path {
- return &Path{
- parent: path,
- IsWithdraw: isWithdraw,
- IsNexthopInvalid: path.IsNexthopInvalid,
- attrsHash: path.attrsHash,
- }
-}
-
-func (path *Path) root() *Path {
- p := path
- for p.parent != nil {
- p = p.parent
- }
- return p
-}
-
-func (path *Path) OriginInfo() *originInfo {
- return path.root().info
-}
-
-func (path *Path) NoImplicitWithdraw() bool {
- return path.OriginInfo().noImplicitWithdraw
-}
-
-func (path *Path) Validation() *Validation {
- return path.OriginInfo().validation
-}
-
-func (path *Path) ValidationStatus() config.RpkiValidationResultType {
- if v := path.OriginInfo().validation; v != nil {
- return v.Status
- } else {
- return config.RPKI_VALIDATION_RESULT_TYPE_NONE
- }
-}
-
-func (path *Path) SetValidation(v *Validation) {
- path.OriginInfo().validation = v
-}
-
-func (path *Path) IsFromExternal() bool {
- return path.OriginInfo().isFromExternal
-}
-
-func (path *Path) SetIsFromExternal(y bool) {
- path.OriginInfo().isFromExternal = y
-}
-
-func (path *Path) GetRouteFamily() bgp.RouteFamily {
- return bgp.AfiSafiToRouteFamily(path.OriginInfo().nlri.AFI(), path.OriginInfo().nlri.SAFI())
-}
-
-func (path *Path) SetSource(source *PeerInfo) {
- path.OriginInfo().source = source
-}
-func (path *Path) GetSource() *PeerInfo {
- return path.OriginInfo().source
-}
-
-func (path *Path) MarkStale(s bool) {
- path.OriginInfo().stale = s
-}
-
-func (path *Path) IsStale() bool {
- return path.OriginInfo().stale
-}
-
-func (path *Path) IsAsLooped() bool {
- return path.aslooped
-}
-
-func (path *Path) SetAsLooped(y bool) {
- path.aslooped = y
-}
-
-func (path *Path) IsLLGRStale() bool {
- for _, c := range path.GetCommunities() {
- if c == uint32(bgp.COMMUNITY_LLGR_STALE) {
- return true
- }
- }
- return false
-}
-
-func (path *Path) GetSourceAs() uint32 {
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- if attr != nil {
- asPathParam := attr.(*bgp.PathAttributeAsPath).Value
- if len(asPathParam) == 0 {
- return 0
- }
- asList := asPathParam[len(asPathParam)-1].GetAS()
- if len(asList) == 0 {
- return 0
- }
- return asList[len(asList)-1]
- }
- return 0
-}
-
-func (path *Path) GetNexthop() net.IP {
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- if attr != nil {
- return attr.(*bgp.PathAttributeNextHop).Value
- }
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- if attr != nil {
- return attr.(*bgp.PathAttributeMpReachNLRI).Nexthop
- }
- return net.IP{}
-}
-
-func (path *Path) SetNexthop(nexthop net.IP) {
- if path.GetRouteFamily() == bgp.RF_IPv4_UC && nexthop.To4() == nil {
- path.delPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- mpreach := bgp.NewPathAttributeMpReachNLRI(nexthop.String(), []bgp.AddrPrefixInterface{path.GetNlri()})
- path.setPathAttr(mpreach)
- return
- }
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- if attr != nil {
- path.setPathAttr(bgp.NewPathAttributeNextHop(nexthop.String()))
- }
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- if attr != nil {
- oldNlri := attr.(*bgp.PathAttributeMpReachNLRI)
- path.setPathAttr(bgp.NewPathAttributeMpReachNLRI(nexthop.String(), oldNlri.Value))
- }
-}
-
-func (path *Path) GetNlri() bgp.AddrPrefixInterface {
- return path.OriginInfo().nlri
-}
-
-type PathAttrs []bgp.PathAttributeInterface
-
-func (a PathAttrs) Len() int {
- return len(a)
-}
-
-func (a PathAttrs) Swap(i, j int) {
- a[i], a[j] = a[j], a[i]
-}
-
-func (a PathAttrs) Less(i, j int) bool {
- return a[i].GetType() < a[j].GetType()
-}
-
-func (path *Path) GetPathAttrs() []bgp.PathAttributeInterface {
- deleted := NewBitmap(math.MaxUint8)
- modified := make(map[uint]bgp.PathAttributeInterface)
- p := path
- for {
- for _, t := range p.dels {
- deleted.Flag(uint(t))
- }
- if p.parent == nil {
- list := PathAttrs(make([]bgp.PathAttributeInterface, 0, len(p.pathAttrs)))
- // we assume that the original pathAttrs are
- // in order, that is, other bgp speakers send
- // attributes in order.
- for _, a := range p.pathAttrs {
- typ := uint(a.GetType())
- if m, ok := modified[typ]; ok {
- list = append(list, m)
- delete(modified, typ)
- } else if !deleted.GetFlag(typ) {
- list = append(list, a)
- }
- }
- if len(modified) > 0 {
- // Huh, some attributes were newly
- // added. So we need to sort...
- for _, m := range modified {
- list = append(list, m)
- }
- sort.Sort(list)
- }
- return list
- } else {
- for _, a := range p.pathAttrs {
- typ := uint(a.GetType())
- if _, ok := modified[typ]; !deleted.GetFlag(typ) && !ok {
- modified[typ] = a
- }
- }
- }
- p = p.parent
- }
-}
-
-func (path *Path) getPathAttr(typ bgp.BGPAttrType) bgp.PathAttributeInterface {
- p := path
- for {
- for _, t := range p.dels {
- if t == typ {
- return nil
- }
- }
- for _, a := range p.pathAttrs {
- if a.GetType() == typ {
- return a
- }
- }
- if p.parent == nil {
- return nil
- }
- p = p.parent
- }
-}
-
-func (path *Path) setPathAttr(a bgp.PathAttributeInterface) {
- if len(path.pathAttrs) == 0 {
- path.pathAttrs = []bgp.PathAttributeInterface{a}
- } else {
- for i, b := range path.pathAttrs {
- if a.GetType() == b.GetType() {
- path.pathAttrs[i] = a
- return
- }
- }
- path.pathAttrs = append(path.pathAttrs, a)
- }
-}
-
-func (path *Path) delPathAttr(typ bgp.BGPAttrType) {
- if len(path.dels) == 0 {
- path.dels = []bgp.BGPAttrType{typ}
- } else {
- path.dels = append(path.dels, typ)
- }
-}
-
-// return Path's string representation
-func (path *Path) String() string {
- s := bytes.NewBuffer(make([]byte, 0, 64))
- if path.IsEOR() {
- s.WriteString(fmt.Sprintf("{ %s EOR | src: %s }", path.GetRouteFamily(), path.GetSource()))
- return s.String()
- }
- s.WriteString(fmt.Sprintf("{ %s | ", path.getPrefix()))
- s.WriteString(fmt.Sprintf("src: %s", path.GetSource()))
- s.WriteString(fmt.Sprintf(", nh: %s", path.GetNexthop()))
- if path.IsNexthopInvalid {
- s.WriteString(" (not reachable)")
- }
- if path.IsWithdraw {
- s.WriteString(", withdraw")
- }
- s.WriteString(" }")
- return s.String()
-}
-
-func (path *Path) getPrefix() string {
- return path.GetNlri().String()
-}
-
-func (path *Path) GetAsPath() *bgp.PathAttributeAsPath {
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- if attr != nil {
- return attr.(*bgp.PathAttributeAsPath)
- }
- return nil
-}
-
-// GetAsPathLen returns the number of AS_PATH
-func (path *Path) GetAsPathLen() int {
-
- var length int = 0
- if aspath := path.GetAsPath(); aspath != nil {
- for _, as := range aspath.Value {
- length += as.ASLen()
- }
- }
- return length
-}
-
-func (path *Path) GetAsString() string {
- s := bytes.NewBuffer(make([]byte, 0, 64))
- if aspath := path.GetAsPath(); aspath != nil {
- return bgp.AsPathString(aspath)
- }
- return s.String()
-}
-
-func (path *Path) GetAsList() []uint32 {
- return path.getAsListOfSpecificType(true, true)
-
-}
-
-func (path *Path) GetAsSeqList() []uint32 {
- return path.getAsListOfSpecificType(true, false)
-
-}
-
-func (path *Path) getAsListOfSpecificType(getAsSeq, getAsSet bool) []uint32 {
- asList := []uint32{}
- if aspath := path.GetAsPath(); aspath != nil {
- for _, param := range aspath.Value {
- segType := param.GetType()
- if getAsSeq && segType == bgp.BGP_ASPATH_ATTR_TYPE_SEQ {
- asList = append(asList, param.GetAS()...)
- continue
- }
- if getAsSet && segType == bgp.BGP_ASPATH_ATTR_TYPE_SET {
- asList = append(asList, param.GetAS()...)
- } else {
- asList = append(asList, 0)
- }
- }
- }
- return asList
-}
-
-func (path *Path) GetLabelString() string {
- return bgp.LabelString(path.GetNlri())
-}
-
-// PrependAsn prepends AS number.
-// This function updates the AS_PATH attribute as follows.
-// (If the peer is in the confederation member AS,
-// replace AS_SEQUENCE in the following sentence with AS_CONFED_SEQUENCE.)
-// 1) if the first path segment of the AS_PATH is of type
-// AS_SEQUENCE, the local system prepends the specified AS num as
-// the last element of the sequence (put it in the left-most
-// position with respect to the position of octets in the
-// protocol message) the specified number of times.
-// If the act of prepending will cause an overflow in the AS_PATH
-// segment (i.e., more than 255 ASes),
-// it SHOULD prepend a new segment of type AS_SEQUENCE
-// and prepend its own AS number to this new segment.
-//
-// 2) if the first path segment of the AS_PATH is of other than type
-// AS_SEQUENCE, the local system prepends a new path segment of type
-// AS_SEQUENCE to the AS_PATH, including the specified AS number in
-// that segment.
-//
-// 3) if the AS_PATH is empty, the local system creates a path
-// segment of type AS_SEQUENCE, places the specified AS number
-// into that segment, and places that segment into the AS_PATH.
-func (path *Path) PrependAsn(asn uint32, repeat uint8, confed bool) {
- var segType uint8
- if confed {
- segType = bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ
- } else {
- segType = bgp.BGP_ASPATH_ATTR_TYPE_SEQ
- }
-
- original := path.GetAsPath()
-
- asns := make([]uint32, repeat)
- for i := range asns {
- asns[i] = asn
- }
-
- var asPath *bgp.PathAttributeAsPath
- if original == nil {
- asPath = bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{})
- } else {
- asPath = cloneAsPath(original)
- }
-
- if len(asPath.Value) > 0 {
- param := asPath.Value[0]
- asList := param.GetAS()
- if param.GetType() == segType {
- if int(repeat)+len(asList) > 255 {
- repeat = uint8(255 - len(asList))
- }
- newAsList := append(asns[:int(repeat)], asList...)
- asPath.Value[0] = bgp.NewAs4PathParam(segType, newAsList)
- asns = asns[int(repeat):]
- }
- }
-
- if len(asns) > 0 {
- p := bgp.NewAs4PathParam(segType, asns)
- asPath.Value = append([]bgp.AsPathParamInterface{p}, asPath.Value...)
- }
- path.setPathAttr(asPath)
-}
-
-func isPrivateAS(as uint32) bool {
- return (64512 <= as && as <= 65534) || (4200000000 <= as && as <= 4294967294)
-}
-
-func (path *Path) RemovePrivateAS(localAS uint32, option config.RemovePrivateAsOption) {
- original := path.GetAsPath()
- if original == nil {
- return
- }
- switch option {
- case config.REMOVE_PRIVATE_AS_OPTION_ALL, config.REMOVE_PRIVATE_AS_OPTION_REPLACE:
- newASParams := make([]bgp.AsPathParamInterface, 0, len(original.Value))
- for _, param := range original.Value {
- asList := param.GetAS()
- newASParam := make([]uint32, 0, len(asList))
- for _, as := range asList {
- if isPrivateAS(as) {
- if option == config.REMOVE_PRIVATE_AS_OPTION_REPLACE {
- newASParam = append(newASParam, localAS)
- }
- } else {
- newASParam = append(newASParam, as)
- }
- }
- if len(newASParam) > 0 {
- newASParams = append(newASParams, bgp.NewAs4PathParam(param.GetType(), newASParam))
- }
- }
- path.setPathAttr(bgp.NewPathAttributeAsPath(newASParams))
- }
-}
-
-func (path *Path) removeConfedAs() {
- original := path.GetAsPath()
- if original == nil {
- return
- }
- newAsParams := make([]bgp.AsPathParamInterface, 0, len(original.Value))
- for _, param := range original.Value {
- switch param.GetType() {
- case bgp.BGP_ASPATH_ATTR_TYPE_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_SET:
- newAsParams = append(newAsParams, param)
- }
- }
- path.setPathAttr(bgp.NewPathAttributeAsPath(newAsParams))
-}
-
-func (path *Path) ReplaceAS(localAS, peerAS uint32) *Path {
- original := path.GetAsPath()
- if original == nil {
- return path
- }
- newASParams := make([]bgp.AsPathParamInterface, 0, len(original.Value))
- changed := false
- for _, param := range original.Value {
- segType := param.GetType()
- asList := param.GetAS()
- newASParam := make([]uint32, 0, len(asList))
- for _, as := range asList {
- if as == peerAS {
- as = localAS
- changed = true
- }
- newASParam = append(newASParam, as)
- }
- newASParams = append(newASParams, bgp.NewAs4PathParam(segType, newASParam))
- }
- if changed {
- path = path.Clone(path.IsWithdraw)
- path.setPathAttr(bgp.NewPathAttributeAsPath(newASParams))
- }
- return path
-}
-
-func (path *Path) GetCommunities() []uint32 {
- communityList := []uint32{}
- if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES); attr != nil {
- communities := attr.(*bgp.PathAttributeCommunities)
- communityList = append(communityList, communities.Value...)
- }
- return communityList
-}
-
-// SetCommunities adds or replaces communities with new ones.
-// If the length of communities is 0 and doReplace is true, it clears communities.
-func (path *Path) SetCommunities(communities []uint32, doReplace bool) {
-
- if len(communities) == 0 && doReplace {
- // clear communities
- path.delPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES)
- return
- }
-
- newList := make([]uint32, 0)
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES)
- if attr != nil {
- c := attr.(*bgp.PathAttributeCommunities)
- if doReplace {
- newList = append(newList, communities...)
- } else {
- newList = append(newList, c.Value...)
- newList = append(newList, communities...)
- }
- } else {
- newList = append(newList, communities...)
- }
- path.setPathAttr(bgp.NewPathAttributeCommunities(newList))
-
-}
-
-// RemoveCommunities removes specific communities.
-// If the length of communities is 0, it does nothing.
-// If all communities are removed, it removes Communities path attribute itself.
-func (path *Path) RemoveCommunities(communities []uint32) int {
-
- if len(communities) == 0 {
- // do nothing
- return 0
- }
-
- find := func(val uint32) bool {
- for _, com := range communities {
- if com == val {
- return true
- }
- }
- return false
- }
-
- count := 0
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES)
- if attr != nil {
- newList := make([]uint32, 0)
- c := attr.(*bgp.PathAttributeCommunities)
-
- for _, value := range c.Value {
- if find(value) {
- count += 1
- } else {
- newList = append(newList, value)
- }
- }
-
- if len(newList) != 0 {
- path.setPathAttr(bgp.NewPathAttributeCommunities(newList))
- } else {
- path.delPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES)
- }
- }
- return count
-}
-
-func (path *Path) GetExtCommunities() []bgp.ExtendedCommunityInterface {
- eCommunityList := make([]bgp.ExtendedCommunityInterface, 0)
- if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES); attr != nil {
- eCommunities := attr.(*bgp.PathAttributeExtendedCommunities).Value
- eCommunityList = append(eCommunityList, eCommunities...)
- }
- return eCommunityList
-}
-
-func (path *Path) SetExtCommunities(exts []bgp.ExtendedCommunityInterface, doReplace bool) {
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
- if attr != nil {
- l := attr.(*bgp.PathAttributeExtendedCommunities).Value
- if doReplace {
- l = exts
- } else {
- l = append(l, exts...)
- }
- path.setPathAttr(bgp.NewPathAttributeExtendedCommunities(l))
- } else {
- path.setPathAttr(bgp.NewPathAttributeExtendedCommunities(exts))
- }
-}
-
-func (path *Path) GetLargeCommunities() []*bgp.LargeCommunity {
- if a := path.getPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY); a != nil {
- v := a.(*bgp.PathAttributeLargeCommunities).Values
- ret := make([]*bgp.LargeCommunity, 0, len(v))
- ret = append(ret, v...)
- return ret
- }
- return nil
-}
-
-func (path *Path) SetLargeCommunities(cs []*bgp.LargeCommunity, doReplace bool) {
- a := path.getPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY)
- if a == nil || doReplace {
- path.setPathAttr(bgp.NewPathAttributeLargeCommunities(cs))
- } else {
- l := a.(*bgp.PathAttributeLargeCommunities).Values
- path.setPathAttr(bgp.NewPathAttributeLargeCommunities(append(l, cs...)))
- }
-}
-
-func (path *Path) GetMed() (uint32, error) {
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- if attr == nil {
- return 0, fmt.Errorf("no med path attr")
- }
- return attr.(*bgp.PathAttributeMultiExitDisc).Value, nil
-}
-
-// SetMed replace, add or subtraction med with new ones.
-func (path *Path) SetMed(med int64, doReplace bool) error {
- parseMed := func(orgMed uint32, med int64, doReplace bool) (*bgp.PathAttributeMultiExitDisc, error) {
- if doReplace {
- return bgp.NewPathAttributeMultiExitDisc(uint32(med)), nil
- }
-
- medVal := int64(orgMed) + med
- if medVal < 0 {
- return nil, fmt.Errorf("med value invalid. it's underflow threshold: %v", medVal)
- } else if medVal > int64(math.MaxUint32) {
- return nil, fmt.Errorf("med value invalid. it's overflow threshold: %v", medVal)
- }
-
- return bgp.NewPathAttributeMultiExitDisc(uint32(int64(orgMed) + med)), nil
- }
-
- m := uint32(0)
- if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC); attr != nil {
- m = attr.(*bgp.PathAttributeMultiExitDisc).Value
- }
- newMed, err := parseMed(m, med, doReplace)
- if err != nil {
- return err
- }
- path.setPathAttr(newMed)
- return nil
-}
-
-func (path *Path) RemoveLocalPref() {
- if path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF) != nil {
- path.delPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF)
- }
-}
-
-func (path *Path) GetOriginatorID() net.IP {
- if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGINATOR_ID); attr != nil {
- return attr.(*bgp.PathAttributeOriginatorId).Value
- }
- return nil
-}
-
-func (path *Path) GetClusterList() []net.IP {
- if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_CLUSTER_LIST); attr != nil {
- return attr.(*bgp.PathAttributeClusterList).Value
- }
- return nil
-}
-
-func (path *Path) GetOrigin() (uint8, error) {
- if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN); attr != nil {
- return attr.(*bgp.PathAttributeOrigin).Value, nil
- }
- return 0, fmt.Errorf("no origin path attr")
-}
-
-func (path *Path) GetLocalPref() (uint32, error) {
- lp := uint32(DEFAULT_LOCAL_PREF)
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF)
- if attr != nil {
- lp = attr.(*bgp.PathAttributeLocalPref).Value
- }
- return lp, nil
-}
-
-func (lhs *Path) Equal(rhs *Path) bool {
- if rhs == nil {
- return false
- }
-
- if lhs.GetSource() != rhs.GetSource() {
- return false
- }
-
- pattrs := func(arg []bgp.PathAttributeInterface) []byte {
- ret := make([]byte, 0)
- for _, a := range arg {
- aa, _ := a.Serialize()
- ret = append(ret, aa...)
- }
- return ret
- }
- return bytes.Equal(pattrs(lhs.GetPathAttrs()), pattrs(rhs.GetPathAttrs()))
-}
-
-func (path *Path) MarshalJSON() ([]byte, error) {
- return json.Marshal(struct {
- Nlri bgp.AddrPrefixInterface `json:"nlri"`
- PathAttrs []bgp.PathAttributeInterface `json:"attrs"`
- Age int64 `json:"age"`
- Withdrawal bool `json:"withdrawal,omitempty"`
- Validation string `json:"validation,omitempty"`
- SourceID net.IP `json:"source-id,omitempty"`
- NeighborIP net.IP `json:"neighbor-ip,omitempty"`
- Stale bool `json:"stale,omitempty"`
- UUID string `json:"uuid,omitempty"`
- ID uint32 `json:"id,omitempty"`
- }{
- Nlri: path.GetNlri(),
- PathAttrs: path.GetPathAttrs(),
- Age: path.GetTimestamp().Unix(),
- Withdrawal: path.IsWithdraw,
- Validation: string(path.ValidationStatus()),
- SourceID: path.GetSource().ID,
- NeighborIP: path.GetSource().Address,
- Stale: path.IsStale(),
- ID: path.GetNlri().PathIdentifier(),
- })
-}
-
-func (lhs *Path) Compare(rhs *Path) int {
- if lhs.IsLocal() && !rhs.IsLocal() {
- return 1
- } else if !lhs.IsLocal() && rhs.IsLocal() {
- return -1
- }
-
- if !lhs.IsIBGP() && rhs.IsIBGP() {
- return 1
- } else if lhs.IsIBGP() && !rhs.IsIBGP() {
- return -1
- }
-
- lp1, _ := lhs.GetLocalPref()
- lp2, _ := rhs.GetLocalPref()
- if lp1 != lp2 {
- return int(lp1 - lp2)
- }
-
- l1 := lhs.GetAsPathLen()
- l2 := rhs.GetAsPathLen()
- if l1 != l2 {
- return int(l2 - l1)
- }
-
- o1, _ := lhs.GetOrigin()
- o2, _ := rhs.GetOrigin()
- if o1 != o2 {
- return int(o2 - o1)
- }
-
- m1, _ := lhs.GetMed()
- m2, _ := rhs.GetMed()
- return int(m2 - m1)
-}
-
-func (v *Vrf) ToGlobalPath(path *Path) error {
- nlri := path.GetNlri()
- switch rf := path.GetRouteFamily(); rf {
- case bgp.RF_IPv4_UC:
- n := nlri.(*bgp.IPAddrPrefix)
- pathIdentifier := path.GetNlri().PathIdentifier()
- path.OriginInfo().nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), v.Rd)
- path.GetNlri().SetPathIdentifier(pathIdentifier)
- case bgp.RF_IPv6_UC:
- n := nlri.(*bgp.IPv6AddrPrefix)
- pathIdentifier := path.GetNlri().PathIdentifier()
- path.OriginInfo().nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), v.Rd)
- path.GetNlri().SetPathIdentifier(pathIdentifier)
- case bgp.RF_EVPN:
- n := nlri.(*bgp.EVPNNLRI)
- switch n.RouteType {
- case bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT:
- n.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute).RD = v.Rd
- case bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG:
- n.RouteTypeData.(*bgp.EVPNMulticastEthernetTagRoute).RD = v.Rd
- }
- default:
- return fmt.Errorf("unsupported route family for vrf: %s", rf)
- }
- path.SetExtCommunities(v.ExportRt, false)
- return nil
-}
-
-func (p *Path) ToGlobal(vrf *Vrf) *Path {
- nlri := p.GetNlri()
- nh := p.GetNexthop()
- pathId := nlri.PathIdentifier()
- switch rf := p.GetRouteFamily(); rf {
- case bgp.RF_IPv4_UC:
- n := nlri.(*bgp.IPAddrPrefix)
- nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd)
- nlri.SetPathIdentifier(pathId)
- case bgp.RF_IPv6_UC:
- n := nlri.(*bgp.IPv6AddrPrefix)
- nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd)
- nlri.SetPathIdentifier(pathId)
- case bgp.RF_EVPN:
- n := nlri.(*bgp.EVPNNLRI)
- switch n.RouteType {
- case bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT:
- old := n.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute)
- new := &bgp.EVPNMacIPAdvertisementRoute{
- RD: vrf.Rd,
- ESI: old.ESI,
- ETag: old.ETag,
- MacAddressLength: old.MacAddressLength,
- MacAddress: old.MacAddress,
- IPAddressLength: old.IPAddressLength,
- IPAddress: old.IPAddress,
- Labels: old.Labels,
- }
- nlri = bgp.NewEVPNNLRI(n.RouteType, new)
- case bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG:
- old := n.RouteTypeData.(*bgp.EVPNMulticastEthernetTagRoute)
- new := &bgp.EVPNMulticastEthernetTagRoute{
- RD: vrf.Rd,
- ETag: old.ETag,
- IPAddressLength: old.IPAddressLength,
- IPAddress: old.IPAddress,
- }
- nlri = bgp.NewEVPNNLRI(n.RouteType, new)
- }
- default:
- return p
- }
- path := NewPath(p.OriginInfo().source, nlri, p.IsWithdraw, p.GetPathAttrs(), p.GetTimestamp(), false)
- path.SetExtCommunities(vrf.ExportRt, false)
- path.delPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- path.setPathAttr(bgp.NewPathAttributeMpReachNLRI(nh.String(), []bgp.AddrPrefixInterface{nlri}))
- path.IsNexthopInvalid = p.IsNexthopInvalid
- return path
-}
-
-func (p *Path) ToLocal() *Path {
- nlri := p.GetNlri()
- f := p.GetRouteFamily()
- pathId := nlri.PathLocalIdentifier()
- switch f {
- case bgp.RF_IPv4_VPN:
- n := nlri.(*bgp.LabeledVPNIPAddrPrefix)
- _, c, _ := net.ParseCIDR(n.IPPrefix())
- ones, _ := c.Mask.Size()
- nlri = bgp.NewIPAddrPrefix(uint8(ones), c.IP.String())
- nlri.SetPathLocalIdentifier(pathId)
- case bgp.RF_IPv6_VPN:
- n := nlri.(*bgp.LabeledVPNIPv6AddrPrefix)
- _, c, _ := net.ParseCIDR(n.IPPrefix())
- ones, _ := c.Mask.Size()
- nlri = bgp.NewIPv6AddrPrefix(uint8(ones), c.IP.String())
- nlri.SetPathLocalIdentifier(pathId)
- default:
- return p
- }
- path := NewPath(p.OriginInfo().source, nlri, p.IsWithdraw, p.GetPathAttrs(), p.GetTimestamp(), false)
- path.delPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
-
- if f == bgp.RF_IPv4_VPN {
- nh := path.GetNexthop()
- path.delPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- path.setPathAttr(bgp.NewPathAttributeNextHop(nh.String()))
- }
- path.IsNexthopInvalid = p.IsNexthopInvalid
- return path
-}
-
-func (p *Path) SetHash(v uint32) {
- p.attrsHash = v
-}
-
-func (p *Path) GetHash() uint32 {
- return p.attrsHash
-}
diff --git a/table/path_test.go b/table/path_test.go
deleted file mode 100644
index 768b76bf..00000000
--- a/table/path_test.go
+++ /dev/null
@@ -1,364 +0,0 @@
-// path_test.go
-package table
-
-import (
- "testing"
- "time"
-
- "github.com/osrg/gobgp/config"
- "github.com/osrg/gobgp/packet/bgp"
- "github.com/stretchr/testify/assert"
-)
-
-func TestPathNewIPv4(t *testing.T) {
- peerP := PathCreatePeer()
- pathP := PathCreatePath(peerP)
- ipv4p := NewPath(pathP[0].GetSource(), pathP[0].GetNlri(), true, pathP[0].GetPathAttrs(), time.Now(), false)
- assert.NotNil(t, ipv4p)
-}
-
-func TestPathNewIPv6(t *testing.T) {
- peerP := PathCreatePeer()
- pathP := PathCreatePath(peerP)
- ipv6p := NewPath(pathP[0].GetSource(), pathP[0].GetNlri(), true, pathP[0].GetPathAttrs(), time.Now(), false)
- assert.NotNil(t, ipv6p)
-}
-
-func TestPathGetNlri(t *testing.T) {
- nlri := bgp.NewIPAddrPrefix(24, "13.2.3.2")
- pd := &Path{
- info: &originInfo{
- nlri: nlri,
- },
- }
- r_nlri := pd.GetNlri()
- assert.Equal(t, r_nlri, nlri)
-}
-
-func TestPathCreatePath(t *testing.T) {
- peerP := PathCreatePeer()
- msg := updateMsgP1()
- updateMsgP := msg.Body.(*bgp.BGPUpdate)
- nlriList := updateMsgP.NLRI
- pathAttributes := updateMsgP.PathAttributes
- nlri_info := nlriList[0]
- path := NewPath(peerP[0], nlri_info, false, pathAttributes, time.Now(), false)
- assert.NotNil(t, path)
-
-}
-
-func TestPathGetPrefix(t *testing.T) {
- peerP := PathCreatePeer()
- pathP := PathCreatePath(peerP)
- prefix := "10.10.10.0/24"
- r_prefix := pathP[0].getPrefix()
- assert.Equal(t, r_prefix, prefix)
-}
-
-func TestPathGetAttribute(t *testing.T) {
- peerP := PathCreatePeer()
- pathP := PathCreatePath(peerP)
- nh := "192.168.50.1"
- pa := pathP[0].getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- r_nh := pa.(*bgp.PathAttributeNextHop).Value.String()
- assert.Equal(t, r_nh, nh)
-}
-
-func TestASPathLen(t *testing.T) {
- assert := assert.New(t)
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint16{65001, 65002, 65003, 65004, 65004, 65004, 65004, 65004, 65005}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SET, []uint16{65001, 65002, 65003, 65004, 65005}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, []uint16{65100, 65101, 65102}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, []uint16{65100, 65101})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpmsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- update := bgpmsg.Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(update)
- peer := PathCreatePeer()
- p := NewPath(peer[0], update.NLRI[0], false, update.PathAttributes, time.Now(), false)
- assert.Equal(10, p.GetAsPathLen())
-}
-
-func TestPathPrependAsnToExistingSeqAttr(t *testing.T) {
- assert := assert.New(t)
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint16{65001, 65002, 65003, 65004, 65005}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SET, []uint16{65001, 65002, 65003, 65004, 65005}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, []uint16{65100, 65101, 65102}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, []uint16{65100, 65101})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpmsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- update := bgpmsg.Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(update)
- peer := PathCreatePeer()
- p := NewPath(peer[0], update.NLRI[0], false, update.PathAttributes, time.Now(), false)
-
- p.PrependAsn(65000, 1, false)
- assert.Equal([]uint32{65000, 65001, 65002, 65003, 65004, 65005, 0, 0, 0}, p.GetAsSeqList())
-}
-
-func TestPathPrependAsnToNewAsPathAttr(t *testing.T) {
- assert := assert.New(t)
- origin := bgp.NewPathAttributeOrigin(0)
- nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- nexthop,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpmsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- update := bgpmsg.Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(update)
- peer := PathCreatePeer()
- p := NewPath(peer[0], update.NLRI[0], false, update.PathAttributes, time.Now(), false)
-
- asn := uint32(65000)
- p.PrependAsn(asn, 1, false)
- assert.Equal([]uint32{asn}, p.GetAsSeqList())
-}
-
-func TestPathPrependAsnToNewAsPathSeq(t *testing.T) {
- assert := assert.New(t)
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SET, []uint16{65001, 65002, 65003, 65004, 65005}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, []uint16{65100, 65101, 65102}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, []uint16{65100, 65101})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpmsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- update := bgpmsg.Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(update)
- peer := PathCreatePeer()
- p := NewPath(peer[0], update.NLRI[0], false, update.PathAttributes, time.Now(), false)
-
- asn := uint32(65000)
- p.PrependAsn(asn, 1, false)
- assert.Equal([]uint32{asn, 0, 0, 0}, p.GetAsSeqList())
-}
-
-func TestPathPrependAsnToEmptyAsPathAttr(t *testing.T) {
- assert := assert.New(t)
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint16{}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SET, []uint16{65001, 65002, 65003, 65004, 65005}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, []uint16{65100, 65101, 65102}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, []uint16{65100, 65101})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpmsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- update := bgpmsg.Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(update)
- peer := PathCreatePeer()
- p := NewPath(peer[0], update.NLRI[0], false, update.PathAttributes, time.Now(), false)
-
- asn := uint32(65000)
- p.PrependAsn(asn, 1, false)
- assert.Equal([]uint32{asn, 0, 0, 0}, p.GetAsSeqList())
-}
-
-func TestPathPrependAsnToFullPathAttr(t *testing.T) {
- assert := assert.New(t)
- origin := bgp.NewPathAttributeOrigin(0)
-
- asns := make([]uint16, 255)
- for i, _ := range asns {
- asns[i] = 65000 + uint16(i)
- }
-
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, asns),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_SET, []uint16{65001, 65002, 65003, 65004, 65005}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, []uint16{65100, 65101, 65102}),
- bgp.NewAsPathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, []uint16{65100, 65101})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpmsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- update := bgpmsg.Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(update)
- peer := PathCreatePeer()
- p := NewPath(peer[0], update.NLRI[0], false, update.PathAttributes, time.Now(), false)
-
- expected := []uint32{65000, 65000}
- for _, v := range asns {
- expected = append(expected, uint32(v))
- }
- p.PrependAsn(65000, 2, false)
- assert.Equal(append(expected, []uint32{0, 0, 0}...), p.GetAsSeqList())
-}
-
-func TestGetPathAttrs(t *testing.T) {
- paths := PathCreatePath(PathCreatePeer())
- path0 := paths[0]
- path1 := path0.Clone(false)
- path1.delPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- path2 := path1.Clone(false)
- path2.setPathAttr(bgp.NewPathAttributeNextHop("192.168.50.1"))
- assert.NotNil(t, path2.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP))
-}
-
-func PathCreatePeer() []*PeerInfo {
- peerP1 := &PeerInfo{AS: 65000}
- peerP2 := &PeerInfo{AS: 65001}
- peerP3 := &PeerInfo{AS: 65002}
- peerP := []*PeerInfo{peerP1, peerP2, peerP3}
- return peerP
-}
-
-func PathCreatePath(peerP []*PeerInfo) []*Path {
- bgpMsgP1 := updateMsgP1()
- bgpMsgP2 := updateMsgP2()
- bgpMsgP3 := updateMsgP3()
- pathP := make([]*Path, 3)
- for i, msg := range []*bgp.BGPMessage{bgpMsgP1, bgpMsgP2, bgpMsgP3} {
- updateMsgP := msg.Body.(*bgp.BGPUpdate)
- nlriList := updateMsgP.NLRI
- pathAttributes := updateMsgP.PathAttributes
- nlri_info := nlriList[0]
- pathP[i] = NewPath(peerP[i], nlri_info, false, pathAttributes, time.Now(), false)
- }
- return pathP
-}
-
-func updateMsgP1() *bgp.BGPMessage {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65000})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- return bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
-}
-
-func updateMsgP2() *bgp.BGPMessage {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65100})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.100.1")
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "20.20.20.0")}
- return bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
-}
-
-func updateMsgP3() *bgp.BGPMessage {
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65100})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.150.1")
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "30.30.30.0")}
- w1 := bgp.NewIPAddrPrefix(23, "40.40.40.0")
- withdrawnRoutes := []*bgp.IPAddrPrefix{w1}
- return bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
-}
-
-func TestRemovePrivateAS(t *testing.T) {
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{64512, 64513, 1, 2})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nlri := bgp.NewIPAddrPrefix(24, "30.30.30.0")
- path := NewPath(nil, nlri, false, []bgp.PathAttributeInterface{aspath}, time.Now(), false)
- path.RemovePrivateAS(10, config.REMOVE_PRIVATE_AS_OPTION_ALL)
- list := path.GetAsList()
- assert.Equal(t, len(list), 2)
- assert.Equal(t, list[0], uint32(1))
- assert.Equal(t, list[1], uint32(2))
-
- path = NewPath(nil, nlri, false, []bgp.PathAttributeInterface{aspath}, time.Now(), false)
- path.RemovePrivateAS(10, config.REMOVE_PRIVATE_AS_OPTION_REPLACE)
- list = path.GetAsList()
- assert.Equal(t, len(list), 4)
- assert.Equal(t, list[0], uint32(10))
- assert.Equal(t, list[1], uint32(10))
- assert.Equal(t, list[2], uint32(1))
- assert.Equal(t, list[3], uint32(2))
-}
-
-func TestReplaceAS(t *testing.T) {
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{64512, 64513, 1, 2})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nlri := bgp.NewIPAddrPrefix(24, "30.30.30.0")
- path := NewPath(nil, nlri, false, []bgp.PathAttributeInterface{aspath}, time.Now(), false)
- path = path.ReplaceAS(10, 1)
- list := path.GetAsList()
- assert.Equal(t, len(list), 4)
- assert.Equal(t, list[0], uint32(64512))
- assert.Equal(t, list[1], uint32(64513))
- assert.Equal(t, list[2], uint32(10))
- assert.Equal(t, list[3], uint32(2))
-}
diff --git a/table/policy.go b/table/policy.go
deleted file mode 100644
index 55d2fc23..00000000
--- a/table/policy.go
+++ /dev/null
@@ -1,3994 +0,0 @@
-// Copyright (C) 2014-2016 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 (
- "bytes"
- "encoding/json"
- "fmt"
- "net"
- "reflect"
- "regexp"
- "sort"
- "strconv"
- "strings"
- "sync"
-
- "github.com/osrg/gobgp/config"
- "github.com/osrg/gobgp/packet/bgp"
-
- radix "github.com/armon/go-radix"
- log "github.com/sirupsen/logrus"
-)
-
-type PolicyOptions struct {
- Info *PeerInfo
- ValidationResult *Validation
- OldNextHop net.IP
-}
-
-type DefinedType int
-
-const (
- DEFINED_TYPE_PREFIX DefinedType = iota
- DEFINED_TYPE_NEIGHBOR
- DEFINED_TYPE_TAG
- DEFINED_TYPE_AS_PATH
- DEFINED_TYPE_COMMUNITY
- DEFINED_TYPE_EXT_COMMUNITY
- DEFINED_TYPE_LARGE_COMMUNITY
- DEFINED_TYPE_NEXT_HOP
-)
-
-type RouteType int
-
-const (
- ROUTE_TYPE_NONE RouteType = iota
- ROUTE_TYPE_ACCEPT
- ROUTE_TYPE_REJECT
-)
-
-func (t RouteType) String() string {
- switch t {
- case ROUTE_TYPE_NONE:
- return "continue"
- case ROUTE_TYPE_ACCEPT:
- return "accept"
- case ROUTE_TYPE_REJECT:
- return "reject"
- }
- return fmt.Sprintf("unknown(%d)", t)
-}
-
-type PolicyDirection int
-
-const (
- POLICY_DIRECTION_NONE PolicyDirection = iota
- POLICY_DIRECTION_IN
- POLICY_DIRECTION_IMPORT
- POLICY_DIRECTION_EXPORT
-)
-
-func (d PolicyDirection) String() string {
- switch d {
- case POLICY_DIRECTION_IN:
- return "in"
- case POLICY_DIRECTION_IMPORT:
- return "import"
- case POLICY_DIRECTION_EXPORT:
- return "export"
- }
- return fmt.Sprintf("unknown(%d)", d)
-}
-
-type MatchOption int
-
-const (
- MATCH_OPTION_ANY MatchOption = iota
- MATCH_OPTION_ALL
- MATCH_OPTION_INVERT
-)
-
-func (o MatchOption) String() string {
- switch o {
- case MATCH_OPTION_ANY:
- return "any"
- case MATCH_OPTION_ALL:
- return "all"
- case MATCH_OPTION_INVERT:
- return "invert"
- default:
- return fmt.Sprintf("MatchOption(%d)", o)
- }
-}
-
-func (o MatchOption) ConvertToMatchSetOptionsRestrictedType() config.MatchSetOptionsRestrictedType {
- switch o {
- case MATCH_OPTION_ANY:
- return config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY
- case MATCH_OPTION_INVERT:
- return config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT
- }
- return "unknown"
-}
-
-type MedActionType int
-
-const (
- MED_ACTION_MOD MedActionType = iota
- MED_ACTION_REPLACE
-)
-
-var CommunityOptionNameMap = map[config.BgpSetCommunityOptionType]string{
- config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD: "add",
- config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE: "remove",
- config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE: "replace",
-}
-
-var CommunityOptionValueMap = map[string]config.BgpSetCommunityOptionType{
- CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD]: config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD,
- CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE]: config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE,
- CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE]: config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE,
-}
-
-type ConditionType int
-
-const (
- CONDITION_PREFIX ConditionType = iota
- CONDITION_NEIGHBOR
- CONDITION_AS_PATH
- CONDITION_COMMUNITY
- CONDITION_EXT_COMMUNITY
- CONDITION_AS_PATH_LENGTH
- CONDITION_RPKI
- CONDITION_ROUTE_TYPE
- CONDITION_LARGE_COMMUNITY
- CONDITION_NEXT_HOP
- CONDITION_AFI_SAFI_IN
-)
-
-type ActionType int
-
-const (
- ACTION_ROUTING ActionType = iota
- ACTION_COMMUNITY
- ACTION_EXT_COMMUNITY
- ACTION_MED
- ACTION_AS_PATH_PREPEND
- ACTION_NEXTHOP
- ACTION_LOCAL_PREF
- ACTION_LARGE_COMMUNITY
-)
-
-func NewMatchOption(c interface{}) (MatchOption, error) {
- switch t := c.(type) {
- case config.MatchSetOptionsType:
- t = t.DefaultAsNeeded()
- switch t {
- case config.MATCH_SET_OPTIONS_TYPE_ANY:
- return MATCH_OPTION_ANY, nil
- case config.MATCH_SET_OPTIONS_TYPE_ALL:
- return MATCH_OPTION_ALL, nil
- case config.MATCH_SET_OPTIONS_TYPE_INVERT:
- return MATCH_OPTION_INVERT, nil
- }
- case config.MatchSetOptionsRestrictedType:
- t = t.DefaultAsNeeded()
- switch t {
- case config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY:
- return MATCH_OPTION_ANY, nil
- case config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT:
- return MATCH_OPTION_INVERT, nil
- }
- }
- return MATCH_OPTION_ANY, fmt.Errorf("invalid argument to create match option: %v", c)
-}
-
-type AttributeComparison int
-
-const (
- // "== comparison"
- ATTRIBUTE_EQ AttributeComparison = iota
- // ">= comparison"
- ATTRIBUTE_GE
- // "<= comparison"
- ATTRIBUTE_LE
-)
-
-func (c AttributeComparison) String() string {
- switch c {
- case ATTRIBUTE_EQ:
- return "="
- case ATTRIBUTE_GE:
- return ">="
- case ATTRIBUTE_LE:
- return "<="
- }
- return "?"
-}
-
-const (
- ASPATH_REGEXP_MAGIC = "(^|[,{}() ]|$)"
-)
-
-type DefinedSet interface {
- Type() DefinedType
- Name() string
- Append(DefinedSet) error
- Remove(DefinedSet) error
- Replace(DefinedSet) error
- String() string
- List() []string
-}
-
-type DefinedSetMap map[DefinedType]map[string]DefinedSet
-
-type DefinedSetList []DefinedSet
-
-func (l DefinedSetList) Len() int {
- return len(l)
-}
-
-func (l DefinedSetList) Swap(i, j int) {
- l[i], l[j] = l[j], l[i]
-}
-
-func (l DefinedSetList) Less(i, j int) bool {
- if l[i].Type() != l[j].Type() {
- return l[i].Type() < l[j].Type()
- }
- return l[i].Name() < l[j].Name()
-}
-
-type Prefix struct {
- Prefix *net.IPNet
- AddressFamily bgp.RouteFamily
- MasklengthRangeMax uint8
- MasklengthRangeMin uint8
-}
-
-func (p *Prefix) Match(path *Path) bool {
- rf := path.GetRouteFamily()
- if rf != p.AddressFamily {
- return false
- }
-
- var pAddr net.IP
- var pMasklen uint8
- switch rf {
- case bgp.RF_IPv4_UC:
- pAddr = path.GetNlri().(*bgp.IPAddrPrefix).Prefix
- pMasklen = path.GetNlri().(*bgp.IPAddrPrefix).Length
- case bgp.RF_IPv6_UC:
- pAddr = path.GetNlri().(*bgp.IPv6AddrPrefix).Prefix
- pMasklen = path.GetNlri().(*bgp.IPv6AddrPrefix).Length
- default:
- return false
- }
-
- return (p.MasklengthRangeMin <= pMasklen && pMasklen <= p.MasklengthRangeMax) && p.Prefix.Contains(pAddr)
-}
-
-func (lhs *Prefix) Equal(rhs *Prefix) bool {
- if lhs == rhs {
- return true
- }
- if rhs == nil {
- return false
- }
- return lhs.Prefix.String() == rhs.Prefix.String() && lhs.MasklengthRangeMin == rhs.MasklengthRangeMin && lhs.MasklengthRangeMax == rhs.MasklengthRangeMax
-}
-
-func (p *Prefix) PrefixString() string {
- isZeros := func(p net.IP) bool {
- for i := 0; i < len(p); i++ {
- if p[i] != 0 {
- return false
- }
- }
- return true
- }
-
- ip := p.Prefix.IP
- if p.AddressFamily == bgp.RF_IPv6_UC && isZeros(ip[0:10]) && ip[10] == 0xff && ip[11] == 0xff {
- m, _ := p.Prefix.Mask.Size()
- return fmt.Sprintf("::FFFF:%s/%d", ip.To16(), m)
- }
- return p.Prefix.String()
-}
-
-var _regexpPrefixRange = regexp.MustCompile(`(\d+)\.\.(\d+)`)
-
-func NewPrefix(c config.Prefix) (*Prefix, error) {
- _, prefix, err := net.ParseCIDR(c.IpPrefix)
- if err != nil {
- return nil, err
- }
-
- rf := bgp.RF_IPv4_UC
- if strings.Contains(c.IpPrefix, ":") {
- rf = bgp.RF_IPv6_UC
- }
- p := &Prefix{
- Prefix: prefix,
- AddressFamily: rf,
- }
- maskRange := c.MasklengthRange
-
- if maskRange == "" {
- l, _ := prefix.Mask.Size()
- maskLength := uint8(l)
- p.MasklengthRangeMax = maskLength
- p.MasklengthRangeMin = maskLength
- return p, nil
- }
-
- elems := _regexpPrefixRange.FindStringSubmatch(maskRange)
- if len(elems) != 3 {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Prefix",
- "MaskRangeFormat": maskRange,
- }).Warn("mask length range format is invalid.")
- return nil, fmt.Errorf("mask length range format is invalid")
- }
-
- // we've already checked the range is sane by regexp
- min, _ := strconv.ParseUint(elems[1], 10, 8)
- max, _ := strconv.ParseUint(elems[2], 10, 8)
- p.MasklengthRangeMin = uint8(min)
- p.MasklengthRangeMax = uint8(max)
- return p, nil
-}
-
-type PrefixSet struct {
- name string
- tree *radix.Tree
- family bgp.RouteFamily
-}
-
-func (s *PrefixSet) Name() string {
- return s.name
-}
-
-func (s *PrefixSet) Type() DefinedType {
- return DEFINED_TYPE_PREFIX
-}
-
-func (lhs *PrefixSet) Append(arg DefinedSet) error {
- rhs, ok := arg.(*PrefixSet)
- if !ok {
- return fmt.Errorf("type cast failed")
- }
- // if either is empty, family can be ignored.
- if lhs.tree.Len() != 0 && rhs.tree.Len() != 0 {
- _, w, _ := lhs.tree.Minimum()
- l := w.([]*Prefix)
- _, v, _ := rhs.tree.Minimum()
- r := v.([]*Prefix)
- if l[0].AddressFamily != r[0].AddressFamily {
- return fmt.Errorf("can't append different family")
- }
- }
- rhs.tree.Walk(func(key string, v interface{}) bool {
- w, ok := lhs.tree.Get(key)
- if ok {
- r := v.([]*Prefix)
- l := w.([]*Prefix)
- lhs.tree.Insert(key, append(l, r...))
- } else {
- lhs.tree.Insert(key, v)
- }
- return false
- })
- _, w, _ := lhs.tree.Minimum()
- lhs.family = w.([]*Prefix)[0].AddressFamily
- return nil
-}
-
-func (lhs *PrefixSet) Remove(arg DefinedSet) error {
- rhs, ok := arg.(*PrefixSet)
- if !ok {
- return fmt.Errorf("type cast failed")
- }
- rhs.tree.Walk(func(key string, v interface{}) bool {
- w, ok := lhs.tree.Get(key)
- if !ok {
- return false
- }
- r := v.([]*Prefix)
- l := w.([]*Prefix)
- new := make([]*Prefix, 0, len(l))
- for _, lp := range l {
- delete := false
- for _, rp := range r {
- if lp.Equal(rp) {
- delete = true
- break
- }
- }
- if !delete {
- new = append(new, lp)
- }
- }
- if len(new) == 0 {
- lhs.tree.Delete(key)
- } else {
- lhs.tree.Insert(key, new)
- }
- return false
- })
- return nil
-}
-
-func (lhs *PrefixSet) Replace(arg DefinedSet) error {
- rhs, ok := arg.(*PrefixSet)
- if !ok {
- return fmt.Errorf("type cast failed")
- }
- lhs.tree = rhs.tree
- lhs.family = rhs.family
- return nil
-}
-
-func (s *PrefixSet) List() []string {
- var list []string
- s.tree.Walk(func(s string, v interface{}) bool {
- ps := v.([]*Prefix)
- for _, p := range ps {
- list = append(list, fmt.Sprintf("%s %d..%d", p.PrefixString(), p.MasklengthRangeMin, p.MasklengthRangeMax))
- }
- return false
- })
- return list
-}
-
-func (s *PrefixSet) ToConfig() *config.PrefixSet {
- list := make([]config.Prefix, 0, s.tree.Len())
- s.tree.Walk(func(s string, v interface{}) bool {
- ps := v.([]*Prefix)
- for _, p := range ps {
- list = append(list, config.Prefix{IpPrefix: p.PrefixString(), MasklengthRange: fmt.Sprintf("%d..%d", p.MasklengthRangeMin, p.MasklengthRangeMax)})
- }
- return false
- })
- return &config.PrefixSet{
- PrefixSetName: s.name,
- PrefixList: list,
- }
-}
-
-func (s *PrefixSet) String() string {
- return strings.Join(s.List(), "\n")
-}
-
-func (s *PrefixSet) MarshalJSON() ([]byte, error) {
- return json.Marshal(s.ToConfig())
-}
-
-func NewPrefixSetFromApiStruct(name string, prefixes []*Prefix) (*PrefixSet, error) {
- if name == "" {
- return nil, fmt.Errorf("empty prefix set name")
- }
- tree := radix.New()
- var family bgp.RouteFamily
- for i, x := range prefixes {
- if i == 0 {
- family = x.AddressFamily
- } else if family != x.AddressFamily {
- return nil, fmt.Errorf("multiple families")
- }
- key := CidrToRadixkey(x.Prefix.String())
- d, ok := tree.Get(key)
- if ok {
- ps := d.([]*Prefix)
- tree.Insert(key, append(ps, x))
- } else {
- tree.Insert(key, []*Prefix{x})
- }
- }
- return &PrefixSet{
- name: name,
- tree: tree,
- family: family,
- }, nil
-}
-
-func NewPrefixSet(c config.PrefixSet) (*PrefixSet, error) {
- name := c.PrefixSetName
- if name == "" {
- if len(c.PrefixList) == 0 {
- return nil, nil
- }
- return nil, fmt.Errorf("empty prefix set name")
- }
- tree := radix.New()
- var family bgp.RouteFamily
- for i, x := range c.PrefixList {
- y, err := NewPrefix(x)
- if err != nil {
- return nil, err
- }
- if i == 0 {
- family = y.AddressFamily
- } else if family != y.AddressFamily {
- return nil, fmt.Errorf("multiple families")
- }
- key := CidrToRadixkey(y.Prefix.String())
- d, ok := tree.Get(key)
- if ok {
- ps := d.([]*Prefix)
- tree.Insert(key, append(ps, y))
- } else {
- tree.Insert(key, []*Prefix{y})
- }
- }
- return &PrefixSet{
- name: name,
- tree: tree,
- family: family,
- }, nil
-}
-
-type NextHopSet struct {
- list []net.IPNet
-}
-
-func (s *NextHopSet) Name() string {
- return "NextHopSet: NO NAME"
-}
-
-func (s *NextHopSet) Type() DefinedType {
- return DEFINED_TYPE_NEXT_HOP
-}
-
-func (lhs *NextHopSet) Append(arg DefinedSet) error {
- rhs, ok := arg.(*NextHopSet)
- if !ok {
- return fmt.Errorf("type cast failed")
- }
- lhs.list = append(lhs.list, rhs.list...)
- return nil
-}
-
-func (lhs *NextHopSet) Remove(arg DefinedSet) error {
- rhs, ok := arg.(*NextHopSet)
- if !ok {
- return fmt.Errorf("type cast failed")
- }
- ps := make([]net.IPNet, 0, len(lhs.list))
- for _, x := range lhs.list {
- found := false
- for _, y := range rhs.list {
- if x.String() == y.String() {
- found = true
- break
- }
- }
- if !found {
- ps = append(ps, x)
- }
- }
- lhs.list = ps
- return nil
-}
-
-func (lhs *NextHopSet) Replace(arg DefinedSet) error {
- rhs, ok := arg.(*NextHopSet)
- if !ok {
- return fmt.Errorf("type cast failed")
- }
- lhs.list = rhs.list
- return nil
-}
-
-func (s *NextHopSet) List() []string {
- list := make([]string, 0, len(s.list))
- for _, n := range s.list {
- list = append(list, n.String())
- }
- return list
-}
-
-func (s *NextHopSet) ToConfig() []string {
- return s.List()
-}
-
-func (s *NextHopSet) String() string {
- return "[ " + strings.Join(s.List(), ", ") + " ]"
-}
-
-func (s *NextHopSet) MarshalJSON() ([]byte, error) {
- return json.Marshal(s.ToConfig())
-}
-
-func NewNextHopSetFromApiStruct(name string, list []net.IPNet) (*NextHopSet, error) {
- return &NextHopSet{
- list: list,
- }, nil
-}
-
-func NewNextHopSet(c []string) (*NextHopSet, error) {
- list := make([]net.IPNet, 0, len(c))
- for _, x := range c {
- _, cidr, err := net.ParseCIDR(x)
- if err != nil {
- addr := net.ParseIP(x)
- if addr == nil {
- return nil, fmt.Errorf("invalid address or prefix: %s", x)
- }
- mask := net.CIDRMask(32, 32)
- if addr.To4() == nil {
- mask = net.CIDRMask(128, 128)
- }
- cidr = &net.IPNet{
- IP: addr,
- Mask: mask,
- }
- }
- list = append(list, *cidr)
- }
- return &NextHopSet{
- list: list,
- }, nil
-}
-
-type NeighborSet struct {
- name string
- list []net.IPNet
-}
-
-func (s *NeighborSet) Name() string {
- return s.name
-}
-
-func (s *NeighborSet) Type() DefinedType {
- return DEFINED_TYPE_NEIGHBOR
-}
-
-func (lhs *NeighborSet) Append(arg DefinedSet) error {
- rhs, ok := arg.(*NeighborSet)
- if !ok {
- return fmt.Errorf("type cast failed")
- }
- lhs.list = append(lhs.list, rhs.list...)
- return nil
-}
-
-func (lhs *NeighborSet) Remove(arg DefinedSet) error {
- rhs, ok := arg.(*NeighborSet)
- if !ok {
- return fmt.Errorf("type cast failed")
- }
- ps := make([]net.IPNet, 0, len(lhs.list))
- for _, x := range lhs.list {
- found := false
- for _, y := range rhs.list {
- if x.String() == y.String() {
- found = true
- break
- }
- }
- if !found {
- ps = append(ps, x)
- }
- }
- lhs.list = ps
- return nil
-}
-
-func (lhs *NeighborSet) Replace(arg DefinedSet) error {
- rhs, ok := arg.(*NeighborSet)
- if !ok {
- return fmt.Errorf("type cast failed")
- }
- lhs.list = rhs.list
- return nil
-}
-
-func (s *NeighborSet) List() []string {
- list := make([]string, 0, len(s.list))
- for _, n := range s.list {
- list = append(list, n.String())
- }
- return list
-}
-
-func (s *NeighborSet) ToConfig() *config.NeighborSet {
- return &config.NeighborSet{
- NeighborSetName: s.name,
- NeighborInfoList: s.List(),
- }
-}
-
-func (s *NeighborSet) String() string {
- return strings.Join(s.List(), "\n")
-}
-
-func (s *NeighborSet) MarshalJSON() ([]byte, error) {
- return json.Marshal(s.ToConfig())
-}
-
-func NewNeighborSetFromApiStruct(name string, list []net.IPNet) (*NeighborSet, error) {
- return &NeighborSet{
- name: name,
- list: list,
- }, nil
-}
-
-func NewNeighborSet(c config.NeighborSet) (*NeighborSet, error) {
- name := c.NeighborSetName
- if name == "" {
- if len(c.NeighborInfoList) == 0 {
- return nil, nil
- }
- return nil, fmt.Errorf("empty neighbor set name")
- }
- list := make([]net.IPNet, 0, len(c.NeighborInfoList))
- for _, x := range c.NeighborInfoList {
- _, cidr, err := net.ParseCIDR(x)
- if err != nil {
- addr := net.ParseIP(x)
- if addr == nil {
- return nil, fmt.Errorf("invalid address or prefix: %s", x)
- }
- mask := net.CIDRMask(32, 32)
- if addr.To4() == nil {
- mask = net.CIDRMask(128, 128)
- }
- cidr = &net.IPNet{
- IP: addr,
- Mask: mask,
- }
- }
- list = append(list, *cidr)
- }
- return &NeighborSet{
- name: name,
- list: list,
- }, nil
-}
-
-type singleAsPathMatchMode int
-
-const (
- INCLUDE singleAsPathMatchMode = iota
- LEFT_MOST
- ORIGIN
- ONLY
-)
-
-type singleAsPathMatch struct {
- asn uint32
- mode singleAsPathMatchMode
-}
-
-func (lhs *singleAsPathMatch) Equal(rhs *singleAsPathMatch) bool {
- return lhs.asn == rhs.asn && lhs.mode == rhs.mode
-}
-
-func (lhs *singleAsPathMatch) String() string {
- switch lhs.mode {
- case INCLUDE:
- return fmt.Sprintf("_%d_", lhs.asn)
- case LEFT_MOST:
- return fmt.Sprintf("^%d_", lhs.asn)
- case ORIGIN:
- return fmt.Sprintf("_%d$", lhs.asn)
- case ONLY:
- return fmt.Sprintf("^%d$", lhs.asn)
- }
- return ""
-}
-
-func (m *singleAsPathMatch) Match(aspath []uint32) bool {
- if len(aspath) == 0 {
- return false
- }
- switch m.mode {
- case INCLUDE:
- for _, asn := range aspath {
- if m.asn == asn {
- return true
- }
- }
- case LEFT_MOST:
- if m.asn == aspath[0] {
- return true
- }
- case ORIGIN:
- if m.asn == aspath[len(aspath)-1] {
- return true
- }
- case ONLY:
- if len(aspath) == 1 && m.asn == aspath[0] {
- return true
- }
- }
- return false
-}
-
-var (
- _regexpLeftMostRe = regexp.MustCompile(`$\^([0-9]+)_^`)
- _regexpOriginRe = regexp.MustCompile(`^_([0-9]+)\$$`)
- _regexpIncludeRe = regexp.MustCompile("^_([0-9]+)_$")
- _regexpOnlyRe = regexp.MustCompile(`^\^([0-9]+)\$$`)
-)
-
-func NewSingleAsPathMatch(arg string) *singleAsPathMatch {
- switch {
- case _regexpLeftMostRe.MatchString(arg):
- asn, _ := strconv.ParseUint(_regexpLeftMostRe.FindStringSubmatch(arg)[1], 10, 32)
- return &singleAsPathMatch{
- asn: uint32(asn),
- mode: LEFT_MOST,
- }
- case _regexpOriginRe.MatchString(arg):
- asn, _ := strconv.ParseUint(_regexpOriginRe.FindStringSubmatch(arg)[1], 10, 32)
- return &singleAsPathMatch{
- asn: uint32(asn),
- mode: ORIGIN,
- }
- case _regexpIncludeRe.MatchString(arg):
- asn, _ := strconv.ParseUint(_regexpIncludeRe.FindStringSubmatch(arg)[1], 10, 32)
- return &singleAsPathMatch{
- asn: uint32(asn),
- mode: INCLUDE,
- }
- case _regexpOnlyRe.MatchString(arg):
- asn, _ := strconv.ParseUint(_regexpOnlyRe.FindStringSubmatch(arg)[1], 10, 32)
- return &singleAsPathMatch{
- asn: uint32(asn),
- mode: ONLY,
- }
- }
- return nil
-}
-
-type AsPathSet struct {
- typ DefinedType
- name string
- list []*regexp.Regexp
- singleList []*singleAsPathMatch
-}
-
-func (s *AsPathSet) Name() string {
- return s.name
-}
-
-func (s *AsPathSet) Type() DefinedType {
- return s.typ
-}
-
-func (lhs *AsPathSet) Append(arg DefinedSet) error {
- if lhs.Type() != arg.Type() {
- return fmt.Errorf("can't append to different type of defined-set")
- }
- lhs.list = append(lhs.list, arg.(*AsPathSet).list...)
- lhs.singleList = append(lhs.singleList, arg.(*AsPathSet).singleList...)
- return nil
-}
-
-func (lhs *AsPathSet) Remove(arg DefinedSet) error {
- if lhs.Type() != arg.Type() {
- return fmt.Errorf("can't append to different type of defined-set")
- }
- newList := make([]*regexp.Regexp, 0, len(lhs.list))
- for _, x := range lhs.list {
- found := false
- for _, y := range arg.(*AsPathSet).list {
- if x.String() == y.String() {
- found = true
- break
- }
- }
- if !found {
- newList = append(newList, x)
- }
- }
- lhs.list = newList
- newSingleList := make([]*singleAsPathMatch, 0, len(lhs.singleList))
- for _, x := range lhs.singleList {
- found := false
- for _, y := range arg.(*AsPathSet).singleList {
- if x.Equal(y) {
- found = true
- break
- }
- }
- if !found {
- newSingleList = append(newSingleList, x)
- }
- }
- lhs.singleList = newSingleList
- return nil
-}
-
-func (lhs *AsPathSet) Replace(arg DefinedSet) error {
- rhs, ok := arg.(*AsPathSet)
- if !ok {
- return fmt.Errorf("type cast failed")
- }
- lhs.list = rhs.list
- lhs.singleList = rhs.singleList
- return nil
-}
-
-func (s *AsPathSet) List() []string {
- list := make([]string, 0, len(s.list)+len(s.singleList))
- for _, exp := range s.singleList {
- list = append(list, exp.String())
- }
- for _, exp := range s.list {
- list = append(list, exp.String())
- }
- return list
-}
-
-func (s *AsPathSet) ToConfig() *config.AsPathSet {
- return &config.AsPathSet{
- AsPathSetName: s.name,
- AsPathList: s.List(),
- }
-}
-
-func (s *AsPathSet) String() string {
- return strings.Join(s.List(), "\n")
-}
-
-func (s *AsPathSet) MarshalJSON() ([]byte, error) {
- return json.Marshal(s.ToConfig())
-}
-
-func NewAsPathSet(c config.AsPathSet) (*AsPathSet, error) {
- name := c.AsPathSetName
- if name == "" {
- if len(c.AsPathList) == 0 {
- return nil, nil
- }
- return nil, fmt.Errorf("empty as-path set name")
- }
- list := make([]*regexp.Regexp, 0, len(c.AsPathList))
- singleList := make([]*singleAsPathMatch, 0, len(c.AsPathList))
- for _, x := range c.AsPathList {
- if s := NewSingleAsPathMatch(x); s != nil {
- singleList = append(singleList, s)
- } else {
- exp, err := regexp.Compile(strings.Replace(x, "_", ASPATH_REGEXP_MAGIC, -1))
- if err != nil {
- return nil, fmt.Errorf("invalid regular expression: %s", x)
- }
- list = append(list, exp)
- }
- }
- return &AsPathSet{
- typ: DEFINED_TYPE_AS_PATH,
- name: name,
- list: list,
- singleList: singleList,
- }, nil
-}
-
-type regExpSet struct {
- typ DefinedType
- name string
- list []*regexp.Regexp
-}
-
-func (s *regExpSet) Name() string {
- return s.name
-}
-
-func (s *regExpSet) Type() DefinedType {
- return s.typ
-}
-
-func (lhs *regExpSet) Append(arg DefinedSet) error {
- if lhs.Type() != arg.Type() {
- return fmt.Errorf("can't append to different type of defined-set")
- }
- var list []*regexp.Regexp
- switch lhs.Type() {
- case DEFINED_TYPE_AS_PATH:
- list = arg.(*AsPathSet).list
- case DEFINED_TYPE_COMMUNITY:
- list = arg.(*CommunitySet).list
- case DEFINED_TYPE_EXT_COMMUNITY:
- list = arg.(*ExtCommunitySet).list
- case DEFINED_TYPE_LARGE_COMMUNITY:
- list = arg.(*LargeCommunitySet).list
- default:
- return fmt.Errorf("invalid defined-set type: %d", lhs.Type())
- }
- lhs.list = append(lhs.list, list...)
- return nil
-}
-
-func (lhs *regExpSet) Remove(arg DefinedSet) error {
- if lhs.Type() != arg.Type() {
- return fmt.Errorf("can't append to different type of defined-set")
- }
- var list []*regexp.Regexp
- switch lhs.Type() {
- case DEFINED_TYPE_AS_PATH:
- list = arg.(*AsPathSet).list
- case DEFINED_TYPE_COMMUNITY:
- list = arg.(*CommunitySet).list
- case DEFINED_TYPE_EXT_COMMUNITY:
- list = arg.(*ExtCommunitySet).list
- case DEFINED_TYPE_LARGE_COMMUNITY:
- list = arg.(*LargeCommunitySet).list
- default:
- return fmt.Errorf("invalid defined-set type: %d", lhs.Type())
- }
- ps := make([]*regexp.Regexp, 0, len(lhs.list))
- for _, x := range lhs.list {
- found := false
- for _, y := range list {
- if x.String() == y.String() {
- found = true
- break
- }
- }
- if !found {
- ps = append(ps, x)
- }
- }
- lhs.list = ps
- return nil
-}
-
-func (lhs *regExpSet) Replace(arg DefinedSet) error {
- switch c := arg.(type) {
- case *CommunitySet:
- lhs.list = c.list
- case *ExtCommunitySet:
- lhs.list = c.list
- case *LargeCommunitySet:
- lhs.list = c.list
- default:
- return fmt.Errorf("type cast failed")
- }
- return nil
-}
-
-type CommunitySet struct {
- regExpSet
-}
-
-func (s *CommunitySet) List() []string {
- list := make([]string, 0, len(s.list))
- for _, exp := range s.list {
- list = append(list, exp.String())
- }
- return list
-}
-
-func (s *CommunitySet) ToConfig() *config.CommunitySet {
- return &config.CommunitySet{
- CommunitySetName: s.name,
- CommunityList: s.List(),
- }
-}
-
-func (s *CommunitySet) String() string {
- return strings.Join(s.List(), "\n")
-}
-
-func (s *CommunitySet) MarshalJSON() ([]byte, error) {
- return json.Marshal(s.ToConfig())
-}
-
-var _regexpCommunity = regexp.MustCompile(`(\d+):(\d+)`)
-
-func ParseCommunity(arg string) (uint32, error) {
- i, err := strconv.ParseUint(arg, 10, 32)
- if err == nil {
- return uint32(i), nil
- }
-
- elems := _regexpCommunity.FindStringSubmatch(arg)
- if len(elems) == 3 {
- fst, _ := strconv.ParseUint(elems[1], 10, 16)
- snd, _ := strconv.ParseUint(elems[2], 10, 16)
- return uint32(fst<<16 | snd), nil
- }
- for i, v := range bgp.WellKnownCommunityNameMap {
- if arg == v {
- return uint32(i), nil
- }
- }
- return 0, fmt.Errorf("failed to parse %s as community", arg)
-}
-
-func ParseExtCommunity(arg string) (bgp.ExtendedCommunityInterface, error) {
- var subtype bgp.ExtendedCommunityAttrSubType
- var value string
- elems := strings.SplitN(arg, ":", 2)
-
- isValidationState := func(s string) bool {
- s = strings.ToLower(s)
- r := s == bgp.VALIDATION_STATE_VALID.String()
- r = r || s == bgp.VALIDATION_STATE_NOT_FOUND.String()
- return r || s == bgp.VALIDATION_STATE_INVALID.String()
- }
- if len(elems) < 2 && (len(elems) < 1 && !isValidationState(elems[0])) {
- return nil, fmt.Errorf("invalid ext-community (rt|soo):<value> | valid | not-found | invalid")
- }
- if isValidationState(elems[0]) {
- subtype = bgp.EC_SUBTYPE_ORIGIN_VALIDATION
- value = elems[0]
- } else {
- switch strings.ToLower(elems[0]) {
- case "rt":
- subtype = bgp.EC_SUBTYPE_ROUTE_TARGET
- case "soo":
- subtype = bgp.EC_SUBTYPE_ROUTE_ORIGIN
- default:
- return nil, fmt.Errorf("invalid ext-community (rt|soo):<value> | valid | not-found | invalid")
- }
- value = elems[1]
- }
- return bgp.ParseExtendedCommunity(subtype, value)
-}
-
-var _regexpCommunity2 = regexp.MustCompile(`(\d+.)*\d+:\d+`)
-
-func ParseCommunityRegexp(arg string) (*regexp.Regexp, error) {
- i, err := strconv.ParseUint(arg, 10, 32)
- if err == nil {
- return regexp.Compile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff))
- }
-
- if _regexpCommunity2.MatchString(arg) {
- return regexp.Compile(fmt.Sprintf("^%s$", arg))
- }
-
- for i, v := range bgp.WellKnownCommunityNameMap {
- if strings.Replace(strings.ToLower(arg), "_", "-", -1) == v {
- return regexp.Compile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff))
- }
- }
-
- return regexp.Compile(arg)
-}
-
-func ParseExtCommunityRegexp(arg string) (bgp.ExtendedCommunityAttrSubType, *regexp.Regexp, error) {
- var subtype bgp.ExtendedCommunityAttrSubType
- elems := strings.SplitN(arg, ":", 2)
- if len(elems) < 2 {
- return subtype, nil, fmt.Errorf("invalid ext-community format([rt|soo]:<value>)")
- }
- switch strings.ToLower(elems[0]) {
- case "rt":
- subtype = bgp.EC_SUBTYPE_ROUTE_TARGET
- case "soo":
- subtype = bgp.EC_SUBTYPE_ROUTE_ORIGIN
- default:
- return subtype, nil, fmt.Errorf("unknown ext-community subtype. rt, soo is supported")
- }
- exp, err := ParseCommunityRegexp(elems[1])
- return subtype, exp, err
-}
-
-func NewCommunitySet(c config.CommunitySet) (*CommunitySet, error) {
- name := c.CommunitySetName
- if name == "" {
- if len(c.CommunityList) == 0 {
- return nil, nil
- }
- return nil, fmt.Errorf("empty community set name")
- }
- list := make([]*regexp.Regexp, 0, len(c.CommunityList))
- for _, x := range c.CommunityList {
- exp, err := ParseCommunityRegexp(x)
- if err != nil {
- return nil, err
- }
- list = append(list, exp)
- }
- return &CommunitySet{
- regExpSet: regExpSet{
- typ: DEFINED_TYPE_COMMUNITY,
- name: name,
- list: list,
- },
- }, nil
-}
-
-type ExtCommunitySet struct {
- regExpSet
- subtypeList []bgp.ExtendedCommunityAttrSubType
-}
-
-func (s *ExtCommunitySet) List() []string {
- list := make([]string, 0, len(s.list))
- f := func(idx int, arg string) string {
- switch s.subtypeList[idx] {
- case bgp.EC_SUBTYPE_ROUTE_TARGET:
- return fmt.Sprintf("rt:%s", arg)
- case bgp.EC_SUBTYPE_ROUTE_ORIGIN:
- return fmt.Sprintf("soo:%s", arg)
- case bgp.EC_SUBTYPE_ORIGIN_VALIDATION:
- return arg
- default:
- return fmt.Sprintf("%d:%s", s.subtypeList[idx], arg)
- }
- }
- for idx, exp := range s.list {
- list = append(list, f(idx, exp.String()))
- }
- return list
-}
-
-func (s *ExtCommunitySet) ToConfig() *config.ExtCommunitySet {
- return &config.ExtCommunitySet{
- ExtCommunitySetName: s.name,
- ExtCommunityList: s.List(),
- }
-}
-
-func (s *ExtCommunitySet) String() string {
- return strings.Join(s.List(), "\n")
-}
-
-func (s *ExtCommunitySet) MarshalJSON() ([]byte, error) {
- return json.Marshal(s.ToConfig())
-}
-
-func NewExtCommunitySet(c config.ExtCommunitySet) (*ExtCommunitySet, error) {
- name := c.ExtCommunitySetName
- if name == "" {
- if len(c.ExtCommunityList) == 0 {
- return nil, nil
- }
- return nil, fmt.Errorf("empty ext-community set name")
- }
- list := make([]*regexp.Regexp, 0, len(c.ExtCommunityList))
- subtypeList := make([]bgp.ExtendedCommunityAttrSubType, 0, len(c.ExtCommunityList))
- for _, x := range c.ExtCommunityList {
- subtype, exp, err := ParseExtCommunityRegexp(x)
- if err != nil {
- return nil, err
- }
- list = append(list, exp)
- subtypeList = append(subtypeList, subtype)
- }
- return &ExtCommunitySet{
- regExpSet: regExpSet{
- typ: DEFINED_TYPE_EXT_COMMUNITY,
- name: name,
- list: list,
- },
- subtypeList: subtypeList,
- }, nil
-}
-
-func (s *ExtCommunitySet) Append(arg DefinedSet) error {
- err := s.regExpSet.Append(arg)
- if err != nil {
- return err
- }
- sList := arg.(*ExtCommunitySet).subtypeList
- s.subtypeList = append(s.subtypeList, sList...)
- return nil
-}
-
-type LargeCommunitySet struct {
- regExpSet
-}
-
-func (s *LargeCommunitySet) List() []string {
- list := make([]string, 0, len(s.list))
- for _, exp := range s.list {
- list = append(list, exp.String())
- }
- return list
-}
-
-func (s *LargeCommunitySet) ToConfig() *config.LargeCommunitySet {
- return &config.LargeCommunitySet{
- LargeCommunitySetName: s.name,
- LargeCommunityList: s.List(),
- }
-}
-
-func (s *LargeCommunitySet) String() string {
- return strings.Join(s.List(), "\n")
-}
-
-func (s *LargeCommunitySet) MarshalJSON() ([]byte, error) {
- return json.Marshal(s.ToConfig())
-}
-
-var _regexpCommunityLarge = regexp.MustCompile(`\d+:\d+:\d+`)
-
-func ParseLargeCommunityRegexp(arg string) (*regexp.Regexp, error) {
- if _regexpCommunityLarge.MatchString(arg) {
- return regexp.Compile(fmt.Sprintf("^%s$", arg))
- }
- exp, err := regexp.Compile(arg)
- if err != nil {
- return nil, fmt.Errorf("invalid large-community format: %v", err)
- }
-
- return exp, nil
-}
-
-func NewLargeCommunitySet(c config.LargeCommunitySet) (*LargeCommunitySet, error) {
- name := c.LargeCommunitySetName
- if name == "" {
- if len(c.LargeCommunityList) == 0 {
- return nil, nil
- }
- return nil, fmt.Errorf("empty large community set name")
- }
- list := make([]*regexp.Regexp, 0, len(c.LargeCommunityList))
- for _, x := range c.LargeCommunityList {
- exp, err := ParseLargeCommunityRegexp(x)
- if err != nil {
- return nil, err
- }
- list = append(list, exp)
- }
- return &LargeCommunitySet{
- regExpSet: regExpSet{
- typ: DEFINED_TYPE_LARGE_COMMUNITY,
- name: name,
- list: list,
- },
- }, nil
-}
-
-type Condition interface {
- Name() string
- Type() ConditionType
- Evaluate(*Path, *PolicyOptions) bool
- Set() DefinedSet
-}
-
-type NextHopCondition struct {
- set *NextHopSet
-}
-
-func (c *NextHopCondition) Type() ConditionType {
- return CONDITION_NEXT_HOP
-}
-
-func (c *NextHopCondition) Set() DefinedSet {
- return c.set
-}
-
-func (c *NextHopCondition) Name() string { return "" }
-
-func (c *NextHopCondition) String() string {
- return c.set.String()
-}
-
-// compare next-hop ipaddress of this condition and source address of path
-// and, subsequent comparisons are skipped if that matches the conditions.
-// If NextHopSet's length is zero, return true.
-func (c *NextHopCondition) Evaluate(path *Path, options *PolicyOptions) bool {
- if len(c.set.list) == 0 {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- }).Debug("NextHop doesn't have elements")
- return true
- }
-
- nexthop := path.GetNexthop()
-
- // In cases where we advertise routes from iBGP to eBGP, we want to filter
- // on the "original" nexthop. The current paths' nexthop has already been
- // set and is ready to be advertised as per:
- // https://tools.ietf.org/html/rfc4271#section-5.1.3
- if options != nil && options.OldNextHop != nil &&
- !options.OldNextHop.IsUnspecified() && !options.OldNextHop.Equal(nexthop) {
- nexthop = options.OldNextHop
- }
-
- if nexthop == nil {
- return false
- }
-
- for _, n := range c.set.list {
- if n.Contains(nexthop) {
- return true
- }
- }
-
- return false
-}
-
-func NewNextHopCondition(c []string) (*NextHopCondition, error) {
- if len(c) == 0 {
- return nil, nil
- }
-
- list, err := NewNextHopSet(c)
- if err != nil {
- return nil, nil
- }
-
- return &NextHopCondition{
- set: list,
- }, nil
-}
-
-type PrefixCondition struct {
- set *PrefixSet
- option MatchOption
-}
-
-func (c *PrefixCondition) Type() ConditionType {
- return CONDITION_PREFIX
-}
-
-func (c *PrefixCondition) Set() DefinedSet {
- return c.set
-}
-
-func (c *PrefixCondition) Option() MatchOption {
- return c.option
-}
-
-// compare prefixes in this condition and nlri of path and
-// subsequent comparison is skipped if that matches the conditions.
-// If PrefixList's length is zero, return true.
-func (c *PrefixCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
- var key string
- var masklen uint8
- keyf := func(ip net.IP, ones int) string {
- var buffer bytes.Buffer
- for i := 0; i < len(ip) && i < ones; i++ {
- buffer.WriteString(fmt.Sprintf("%08b", ip[i]))
- }
- return buffer.String()[:ones]
- }
- family := path.GetRouteFamily()
- switch family {
- case bgp.RF_IPv4_UC:
- masklen = path.GetNlri().(*bgp.IPAddrPrefix).Length
- key = keyf(path.GetNlri().(*bgp.IPAddrPrefix).Prefix, int(masklen))
- case bgp.RF_IPv6_UC:
- masklen = path.GetNlri().(*bgp.IPv6AddrPrefix).Length
- key = keyf(path.GetNlri().(*bgp.IPv6AddrPrefix).Prefix, int(masklen))
- default:
- return false
- }
- if family != c.set.family {
- return false
- }
-
- result := false
- _, ps, ok := c.set.tree.LongestPrefix(key)
- if ok {
- for _, p := range ps.([]*Prefix) {
- if p.MasklengthRangeMin <= masklen && masklen <= p.MasklengthRangeMax {
- result = true
- break
- }
- }
- }
-
- if c.option == MATCH_OPTION_INVERT {
- result = !result
- }
-
- return result
-}
-
-func (c *PrefixCondition) Name() string { return c.set.name }
-
-func NewPrefixCondition(c config.MatchPrefixSet) (*PrefixCondition, error) {
- if c.PrefixSet == "" {
- return nil, nil
- }
- o, err := NewMatchOption(c.MatchSetOptions)
- if err != nil {
- return nil, err
- }
- return &PrefixCondition{
- set: &PrefixSet{
- name: c.PrefixSet,
- },
- option: o,
- }, nil
-}
-
-type NeighborCondition struct {
- set *NeighborSet
- option MatchOption
-}
-
-func (c *NeighborCondition) Type() ConditionType {
- return CONDITION_NEIGHBOR
-}
-
-func (c *NeighborCondition) Set() DefinedSet {
- return c.set
-}
-
-func (c *NeighborCondition) Option() MatchOption {
- return c.option
-}
-
-// compare neighbor ipaddress of this condition and source address of path
-// and, subsequent comparisons are skipped if that matches the conditions.
-// If NeighborList's length is zero, return true.
-func (c *NeighborCondition) Evaluate(path *Path, options *PolicyOptions) bool {
- if len(c.set.list) == 0 {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- }).Debug("NeighborList doesn't have elements")
- return true
- }
-
- neighbor := path.GetSource().Address
- if options != nil && options.Info != nil && options.Info.Address != nil {
- neighbor = options.Info.Address
- }
-
- if neighbor == nil {
- return false
- }
- result := false
- for _, n := range c.set.list {
- if n.Contains(neighbor) {
- result = true
- break
- }
- }
-
- if c.option == MATCH_OPTION_INVERT {
- result = !result
- }
-
- return result
-}
-
-func (c *NeighborCondition) Name() string { return c.set.name }
-
-func NewNeighborCondition(c config.MatchNeighborSet) (*NeighborCondition, error) {
- if c.NeighborSet == "" {
- return nil, nil
- }
- o, err := NewMatchOption(c.MatchSetOptions)
- if err != nil {
- return nil, err
- }
- return &NeighborCondition{
- set: &NeighborSet{
- name: c.NeighborSet,
- },
- option: o,
- }, nil
-}
-
-type AsPathCondition struct {
- set *AsPathSet
- option MatchOption
-}
-
-func (c *AsPathCondition) Type() ConditionType {
- return CONDITION_AS_PATH
-}
-
-func (c *AsPathCondition) Set() DefinedSet {
- return c.set
-}
-
-func (c *AsPathCondition) Option() MatchOption {
- return c.option
-}
-
-func (c *AsPathCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
- if len(c.set.singleList) > 0 {
- aspath := path.GetAsSeqList()
- for _, m := range c.set.singleList {
- result := m.Match(aspath)
- if c.option == MATCH_OPTION_ALL && !result {
- return false
- }
- if c.option == MATCH_OPTION_ANY && result {
- return true
- }
- if c.option == MATCH_OPTION_INVERT && result {
- return false
- }
- }
- }
- if len(c.set.list) > 0 {
- aspath := path.GetAsString()
- for _, r := range c.set.list {
- result := r.MatchString(aspath)
- if c.option == MATCH_OPTION_ALL && !result {
- return false
- }
- if c.option == MATCH_OPTION_ANY && result {
- return true
- }
- if c.option == MATCH_OPTION_INVERT && result {
- return false
- }
- }
- }
- if c.option == MATCH_OPTION_ANY {
- return false
- }
- return true
-}
-
-func (c *AsPathCondition) Name() string { return c.set.name }
-
-func NewAsPathCondition(c config.MatchAsPathSet) (*AsPathCondition, error) {
- if c.AsPathSet == "" {
- return nil, nil
- }
- o, err := NewMatchOption(c.MatchSetOptions)
- if err != nil {
- return nil, err
- }
- return &AsPathCondition{
- set: &AsPathSet{
- name: c.AsPathSet,
- },
- option: o,
- }, nil
-}
-
-type CommunityCondition struct {
- set *CommunitySet
- option MatchOption
-}
-
-func (c *CommunityCondition) Type() ConditionType {
- return CONDITION_COMMUNITY
-}
-
-func (c *CommunityCondition) Set() DefinedSet {
- return c.set
-}
-
-func (c *CommunityCondition) Option() MatchOption {
- return c.option
-}
-
-func (c *CommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
- cs := path.GetCommunities()
- result := false
- for _, x := range c.set.list {
- result = false
- for _, y := range cs {
- if x.MatchString(fmt.Sprintf("%d:%d", y>>16, y&0x0000ffff)) {
- result = true
- break
- }
- }
- if c.option == MATCH_OPTION_ALL && !result {
- break
- }
- if (c.option == MATCH_OPTION_ANY || c.option == MATCH_OPTION_INVERT) && result {
- break
- }
- }
- if c.option == MATCH_OPTION_INVERT {
- result = !result
- }
- return result
-}
-
-func (c *CommunityCondition) Name() string { return c.set.name }
-
-func NewCommunityCondition(c config.MatchCommunitySet) (*CommunityCondition, error) {
- if c.CommunitySet == "" {
- return nil, nil
- }
- o, err := NewMatchOption(c.MatchSetOptions)
- if err != nil {
- return nil, err
- }
- return &CommunityCondition{
- set: &CommunitySet{
- regExpSet: regExpSet{
- name: c.CommunitySet,
- },
- },
- option: o,
- }, nil
-}
-
-type ExtCommunityCondition struct {
- set *ExtCommunitySet
- option MatchOption
-}
-
-func (c *ExtCommunityCondition) Type() ConditionType {
- return CONDITION_EXT_COMMUNITY
-}
-
-func (c *ExtCommunityCondition) Set() DefinedSet {
- return c.set
-}
-
-func (c *ExtCommunityCondition) Option() MatchOption {
- return c.option
-}
-
-func (c *ExtCommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
- es := path.GetExtCommunities()
- result := false
- for _, x := range es {
- result = false
- typ, subtype := x.GetTypes()
- // match only with transitive community. see RFC7153
- if typ >= 0x3f {
- continue
- }
- for idx, y := range c.set.list {
- if subtype == c.set.subtypeList[idx] && y.MatchString(x.String()) {
- result = true
- break
- }
- }
- if c.option == MATCH_OPTION_ALL && !result {
- break
- }
- if c.option == MATCH_OPTION_ANY && result {
- break
- }
- }
- if c.option == MATCH_OPTION_INVERT {
- result = !result
- }
- return result
-}
-
-func (c *ExtCommunityCondition) Name() string { return c.set.name }
-
-func NewExtCommunityCondition(c config.MatchExtCommunitySet) (*ExtCommunityCondition, error) {
- if c.ExtCommunitySet == "" {
- return nil, nil
- }
- o, err := NewMatchOption(c.MatchSetOptions)
- if err != nil {
- return nil, err
- }
- return &ExtCommunityCondition{
- set: &ExtCommunitySet{
- regExpSet: regExpSet{
- name: c.ExtCommunitySet,
- },
- },
- option: o,
- }, nil
-}
-
-type LargeCommunityCondition struct {
- set *LargeCommunitySet
- option MatchOption
-}
-
-func (c *LargeCommunityCondition) Type() ConditionType {
- return CONDITION_LARGE_COMMUNITY
-}
-
-func (c *LargeCommunityCondition) Set() DefinedSet {
- return c.set
-}
-
-func (c *LargeCommunityCondition) Option() MatchOption {
- return c.option
-}
-
-func (c *LargeCommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
- result := false
- cs := path.GetLargeCommunities()
- for _, x := range c.set.list {
- result = false
- for _, y := range cs {
- if x.MatchString(y.String()) {
- result = true
- break
- }
- }
- if c.option == MATCH_OPTION_ALL && !result {
- break
- }
- if (c.option == MATCH_OPTION_ANY || c.option == MATCH_OPTION_INVERT) && result {
- break
- }
- }
- if c.option == MATCH_OPTION_INVERT {
- result = !result
- }
- return result
-}
-
-func (c *LargeCommunityCondition) Name() string { return c.set.name }
-
-func NewLargeCommunityCondition(c config.MatchLargeCommunitySet) (*LargeCommunityCondition, error) {
- if c.LargeCommunitySet == "" {
- return nil, nil
- }
- o, err := NewMatchOption(c.MatchSetOptions)
- if err != nil {
- return nil, err
- }
- return &LargeCommunityCondition{
- set: &LargeCommunitySet{
- regExpSet: regExpSet{
- name: c.LargeCommunitySet,
- },
- },
- option: o,
- }, nil
-}
-
-type AsPathLengthCondition struct {
- length uint32
- operator AttributeComparison
-}
-
-func (c *AsPathLengthCondition) Type() ConditionType {
- return CONDITION_AS_PATH_LENGTH
-}
-
-// compare AS_PATH length in the message's AS_PATH attribute with
-// the one in condition.
-func (c *AsPathLengthCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
-
- length := uint32(path.GetAsPathLen())
- result := false
- switch c.operator {
- case ATTRIBUTE_EQ:
- result = c.length == length
- case ATTRIBUTE_GE:
- result = c.length <= length
- case ATTRIBUTE_LE:
- result = c.length >= length
- }
-
- return result
-}
-
-func (c *AsPathLengthCondition) Set() DefinedSet {
- return nil
-}
-
-func (c *AsPathLengthCondition) Name() string { return "" }
-
-func (c *AsPathLengthCondition) String() string {
- return fmt.Sprintf("%s%d", c.operator, c.length)
-}
-
-func NewAsPathLengthCondition(c config.AsPathLength) (*AsPathLengthCondition, error) {
- if c.Value == 0 && c.Operator == "" {
- return nil, nil
- }
- var op AttributeComparison
- if i := c.Operator.ToInt(); i < 0 {
- return nil, fmt.Errorf("invalid as path length operator: %s", c.Operator)
- } else {
- // take mod 3 because we have extended openconfig attribute-comparison
- // for simple configuration. see config.AttributeComparison definition
- op = AttributeComparison(i % 3)
- }
- return &AsPathLengthCondition{
- length: c.Value,
- operator: op,
- }, nil
-}
-
-type RpkiValidationCondition struct {
- result config.RpkiValidationResultType
-}
-
-func (c *RpkiValidationCondition) Type() ConditionType {
- return CONDITION_RPKI
-}
-
-func (c *RpkiValidationCondition) Evaluate(path *Path, options *PolicyOptions) bool {
- if options != nil && options.ValidationResult != nil {
- return c.result == options.ValidationResult.Status
- }
- return false
-}
-
-func (c *RpkiValidationCondition) Set() DefinedSet {
- return nil
-}
-
-func (c *RpkiValidationCondition) Name() string { return "" }
-
-func (c *RpkiValidationCondition) String() string {
- return string(c.result)
-}
-
-func NewRpkiValidationCondition(c config.RpkiValidationResultType) (*RpkiValidationCondition, error) {
- if c == config.RpkiValidationResultType("") || c == config.RPKI_VALIDATION_RESULT_TYPE_NONE {
- return nil, nil
- }
- return &RpkiValidationCondition{
- result: c,
- }, nil
-}
-
-type RouteTypeCondition struct {
- typ config.RouteType
-}
-
-func (c *RouteTypeCondition) Type() ConditionType {
- return CONDITION_ROUTE_TYPE
-}
-
-func (c *RouteTypeCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
- switch c.typ {
- case config.ROUTE_TYPE_LOCAL:
- return path.IsLocal()
- case config.ROUTE_TYPE_INTERNAL:
- return !path.IsLocal() && path.IsIBGP()
- case config.ROUTE_TYPE_EXTERNAL:
- return !path.IsLocal() && !path.IsIBGP()
- }
- return false
-}
-
-func (c *RouteTypeCondition) Set() DefinedSet {
- return nil
-}
-
-func (c *RouteTypeCondition) Name() string { return "" }
-
-func (c *RouteTypeCondition) String() string {
- return string(c.typ)
-}
-
-func NewRouteTypeCondition(c config.RouteType) (*RouteTypeCondition, error) {
- if string(c) == "" || c == config.ROUTE_TYPE_NONE {
- return nil, nil
- }
- if err := c.Validate(); err != nil {
- return nil, err
- }
- return &RouteTypeCondition{
- typ: c,
- }, nil
-}
-
-type AfiSafiInCondition struct {
- routeFamilies []bgp.RouteFamily
-}
-
-func (c *AfiSafiInCondition) Type() ConditionType {
- return CONDITION_AFI_SAFI_IN
-}
-
-func (c *AfiSafiInCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
- for _, rf := range c.routeFamilies {
- if path.GetRouteFamily() == rf {
- return true
- }
- }
- return false
-}
-
-func (c *AfiSafiInCondition) Set() DefinedSet {
- return nil
-}
-
-func (c *AfiSafiInCondition) Name() string { return "" }
-
-func (c *AfiSafiInCondition) String() string {
- tmp := make([]string, 0, len(c.routeFamilies))
- for _, afiSafi := range c.routeFamilies {
- tmp = append(tmp, afiSafi.String())
- }
- return strings.Join(tmp, " ")
-}
-
-func NewAfiSafiInCondition(afiSafInConfig []config.AfiSafiType) (*AfiSafiInCondition, error) {
- if afiSafInConfig == nil {
- return nil, nil
- }
-
- routeFamilies := make([]bgp.RouteFamily, 0, len(afiSafInConfig))
- for _, afiSafiValue := range afiSafInConfig {
- if err := afiSafiValue.Validate(); err != nil {
- return nil, err
- }
- rf, err := bgp.GetRouteFamily(string(afiSafiValue))
- if err != nil {
- return nil, err
- }
- routeFamilies = append(routeFamilies, rf)
- }
- return &AfiSafiInCondition{
- routeFamilies: routeFamilies,
- }, nil
-}
-
-type Action interface {
- Type() ActionType
- Apply(*Path, *PolicyOptions) *Path
- String() string
-}
-
-type RoutingAction struct {
- AcceptRoute bool
-}
-
-func (a *RoutingAction) Type() ActionType {
- return ACTION_ROUTING
-}
-
-func (a *RoutingAction) Apply(path *Path, _ *PolicyOptions) *Path {
- if a.AcceptRoute {
- return path
- }
- return nil
-}
-
-func (a *RoutingAction) String() string {
- action := "reject"
- if a.AcceptRoute {
- action = "accept"
- }
- return action
-}
-
-func NewRoutingAction(c config.RouteDisposition) (*RoutingAction, error) {
- var accept bool
- switch c {
- case config.RouteDisposition(""), config.ROUTE_DISPOSITION_NONE:
- return nil, nil
- case config.ROUTE_DISPOSITION_ACCEPT_ROUTE:
- accept = true
- case config.ROUTE_DISPOSITION_REJECT_ROUTE:
- accept = false
- default:
- return nil, fmt.Errorf("invalid route disposition")
- }
- return &RoutingAction{
- AcceptRoute: accept,
- }, nil
-}
-
-type CommunityAction struct {
- action config.BgpSetCommunityOptionType
- list []uint32
- removeList []*regexp.Regexp
-}
-
-func RegexpRemoveCommunities(path *Path, exps []*regexp.Regexp) {
- comms := path.GetCommunities()
- newComms := make([]uint32, 0, len(comms))
- for _, comm := range comms {
- c := fmt.Sprintf("%d:%d", comm>>16, comm&0x0000ffff)
- match := false
- for _, exp := range exps {
- if exp.MatchString(c) {
- match = true
- break
- }
- }
- if !match {
- newComms = append(newComms, comm)
- }
- }
- path.SetCommunities(newComms, true)
-}
-
-func RegexpRemoveExtCommunities(path *Path, exps []*regexp.Regexp, subtypes []bgp.ExtendedCommunityAttrSubType) {
- comms := path.GetExtCommunities()
- newComms := make([]bgp.ExtendedCommunityInterface, 0, len(comms))
- for _, comm := range comms {
- match := false
- typ, subtype := comm.GetTypes()
- // match only with transitive community. see RFC7153
- if typ >= 0x3f {
- continue
- }
- for idx, exp := range exps {
- if subtype == subtypes[idx] && exp.MatchString(comm.String()) {
- match = true
- break
- }
- }
- if !match {
- newComms = append(newComms, comm)
- }
- }
- path.SetExtCommunities(newComms, true)
-}
-
-func RegexpRemoveLargeCommunities(path *Path, exps []*regexp.Regexp) {
- comms := path.GetLargeCommunities()
- newComms := make([]*bgp.LargeCommunity, 0, len(comms))
- for _, comm := range comms {
- c := comm.String()
- match := false
- for _, exp := range exps {
- if exp.MatchString(c) {
- match = true
- break
- }
- }
- if !match {
- newComms = append(newComms, comm)
- }
- }
- path.SetLargeCommunities(newComms, true)
-}
-
-func (a *CommunityAction) Type() ActionType {
- return ACTION_COMMUNITY
-}
-
-func (a *CommunityAction) Apply(path *Path, _ *PolicyOptions) *Path {
- switch a.action {
- case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD:
- path.SetCommunities(a.list, false)
- case config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE:
- RegexpRemoveCommunities(path, a.removeList)
- case config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE:
- path.SetCommunities(a.list, true)
- }
- return path
-}
-
-func (a *CommunityAction) ToConfig() *config.SetCommunity {
- cs := make([]string, 0, len(a.list)+len(a.removeList))
- for _, comm := range a.list {
- c := fmt.Sprintf("%d:%d", comm>>16, comm&0x0000ffff)
- cs = append(cs, c)
- }
- for _, exp := range a.removeList {
- cs = append(cs, exp.String())
- }
- return &config.SetCommunity{
- Options: string(a.action),
- SetCommunityMethod: config.SetCommunityMethod{CommunitiesList: cs},
- }
-}
-
-func (a *CommunityAction) MarshalJSON() ([]byte, error) {
- return json.Marshal(a.ToConfig())
-}
-
-// TODO: this is not efficient use of regexp, probably slow
-var _regexpCommunityReplaceString = regexp.MustCompile(`[\^\$]`)
-
-func (a *CommunityAction) String() string {
- list := a.ToConfig().SetCommunityMethod.CommunitiesList
- l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "")
- return fmt.Sprintf("%s[%s]", a.action, l)
-}
-
-func NewCommunityAction(c config.SetCommunity) (*CommunityAction, error) {
- a, ok := CommunityOptionValueMap[strings.ToLower(c.Options)]
- if !ok {
- if len(c.SetCommunityMethod.CommunitiesList) == 0 {
- return nil, nil
- }
- return nil, fmt.Errorf("invalid option name: %s", c.Options)
- }
- var list []uint32
- var removeList []*regexp.Regexp
- if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
- removeList = make([]*regexp.Regexp, 0, len(c.SetCommunityMethod.CommunitiesList))
- } else {
- list = make([]uint32, 0, len(c.SetCommunityMethod.CommunitiesList))
- }
- for _, x := range c.SetCommunityMethod.CommunitiesList {
- if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
- exp, err := ParseCommunityRegexp(x)
- if err != nil {
- return nil, err
- }
- removeList = append(removeList, exp)
- } else {
- comm, err := ParseCommunity(x)
- if err != nil {
- return nil, err
- }
- list = append(list, comm)
- }
- }
- return &CommunityAction{
- action: a,
- list: list,
- removeList: removeList,
- }, nil
-}
-
-type ExtCommunityAction struct {
- action config.BgpSetCommunityOptionType
- list []bgp.ExtendedCommunityInterface
- removeList []*regexp.Regexp
- subtypeList []bgp.ExtendedCommunityAttrSubType
-}
-
-func (a *ExtCommunityAction) Type() ActionType {
- return ACTION_EXT_COMMUNITY
-}
-
-func (a *ExtCommunityAction) Apply(path *Path, _ *PolicyOptions) *Path {
- switch a.action {
- case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD:
- path.SetExtCommunities(a.list, false)
- case config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE:
- RegexpRemoveExtCommunities(path, a.removeList, a.subtypeList)
- case config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE:
- path.SetExtCommunities(a.list, true)
- }
- return path
-}
-
-func (a *ExtCommunityAction) ToConfig() *config.SetExtCommunity {
- cs := make([]string, 0, len(a.list)+len(a.removeList))
- f := func(idx int, arg string) string {
- switch a.subtypeList[idx] {
- case bgp.EC_SUBTYPE_ROUTE_TARGET:
- return fmt.Sprintf("rt:%s", arg)
- case bgp.EC_SUBTYPE_ROUTE_ORIGIN:
- return fmt.Sprintf("soo:%s", arg)
- case bgp.EC_SUBTYPE_ORIGIN_VALIDATION:
- return arg
- default:
- return fmt.Sprintf("%d:%s", a.subtypeList[idx], arg)
- }
- }
- for idx, c := range a.list {
- cs = append(cs, f(idx, c.String()))
- }
- for idx, exp := range a.removeList {
- cs = append(cs, f(idx, exp.String()))
- }
- return &config.SetExtCommunity{
- Options: string(a.action),
- SetExtCommunityMethod: config.SetExtCommunityMethod{
- CommunitiesList: cs,
- },
- }
-}
-
-func (a *ExtCommunityAction) String() string {
- list := a.ToConfig().SetExtCommunityMethod.CommunitiesList
- l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "")
- return fmt.Sprintf("%s[%s]", a.action, l)
-}
-
-func (a *ExtCommunityAction) MarshalJSON() ([]byte, error) {
- return json.Marshal(a.ToConfig())
-}
-
-func NewExtCommunityAction(c config.SetExtCommunity) (*ExtCommunityAction, error) {
- a, ok := CommunityOptionValueMap[strings.ToLower(c.Options)]
- if !ok {
- if len(c.SetExtCommunityMethod.CommunitiesList) == 0 {
- return nil, nil
- }
- return nil, fmt.Errorf("invalid option name: %s", c.Options)
- }
- var list []bgp.ExtendedCommunityInterface
- var removeList []*regexp.Regexp
- subtypeList := make([]bgp.ExtendedCommunityAttrSubType, 0, len(c.SetExtCommunityMethod.CommunitiesList))
- if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
- removeList = make([]*regexp.Regexp, 0, len(c.SetExtCommunityMethod.CommunitiesList))
- } else {
- list = make([]bgp.ExtendedCommunityInterface, 0, len(c.SetExtCommunityMethod.CommunitiesList))
- }
- for _, x := range c.SetExtCommunityMethod.CommunitiesList {
- if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
- subtype, exp, err := ParseExtCommunityRegexp(x)
- if err != nil {
- return nil, err
- }
- removeList = append(removeList, exp)
- subtypeList = append(subtypeList, subtype)
- } else {
- comm, err := ParseExtCommunity(x)
- if err != nil {
- return nil, err
- }
- list = append(list, comm)
- _, subtype := comm.GetTypes()
- subtypeList = append(subtypeList, subtype)
- }
- }
- return &ExtCommunityAction{
- action: a,
- list: list,
- removeList: removeList,
- subtypeList: subtypeList,
- }, nil
-}
-
-type LargeCommunityAction struct {
- action config.BgpSetCommunityOptionType
- list []*bgp.LargeCommunity
- removeList []*regexp.Regexp
-}
-
-func (a *LargeCommunityAction) Type() ActionType {
- return ACTION_LARGE_COMMUNITY
-}
-
-func (a *LargeCommunityAction) Apply(path *Path, _ *PolicyOptions) *Path {
- switch a.action {
- case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD:
- path.SetLargeCommunities(a.list, false)
- case config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE:
- RegexpRemoveLargeCommunities(path, a.removeList)
- case config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE:
- path.SetLargeCommunities(a.list, true)
- }
- return path
-}
-
-func (a *LargeCommunityAction) ToConfig() *config.SetLargeCommunity {
- cs := make([]string, 0, len(a.list)+len(a.removeList))
- for _, comm := range a.list {
- cs = append(cs, comm.String())
- }
- for _, exp := range a.removeList {
- cs = append(cs, exp.String())
- }
- return &config.SetLargeCommunity{
- SetLargeCommunityMethod: config.SetLargeCommunityMethod{CommunitiesList: cs},
- Options: config.BgpSetCommunityOptionType(a.action),
- }
-}
-
-func (a *LargeCommunityAction) String() string {
- list := a.ToConfig().SetLargeCommunityMethod.CommunitiesList
- l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "")
- return fmt.Sprintf("%s[%s]", a.action, l)
-}
-
-func (a *LargeCommunityAction) MarshalJSON() ([]byte, error) {
- return json.Marshal(a.ToConfig())
-}
-
-func NewLargeCommunityAction(c config.SetLargeCommunity) (*LargeCommunityAction, error) {
- a, ok := CommunityOptionValueMap[strings.ToLower(string(c.Options))]
- if !ok {
- if len(c.SetLargeCommunityMethod.CommunitiesList) == 0 {
- return nil, nil
- }
- return nil, fmt.Errorf("invalid option name: %s", c.Options)
- }
- var list []*bgp.LargeCommunity
- var removeList []*regexp.Regexp
- if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
- removeList = make([]*regexp.Regexp, 0, len(c.SetLargeCommunityMethod.CommunitiesList))
- } else {
- list = make([]*bgp.LargeCommunity, 0, len(c.SetLargeCommunityMethod.CommunitiesList))
- }
- for _, x := range c.SetLargeCommunityMethod.CommunitiesList {
- if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
- exp, err := ParseLargeCommunityRegexp(x)
- if err != nil {
- return nil, err
- }
- removeList = append(removeList, exp)
- } else {
- comm, err := bgp.ParseLargeCommunity(x)
- if err != nil {
- return nil, err
- }
- list = append(list, comm)
- }
- }
- return &LargeCommunityAction{
- action: a,
- list: list,
- removeList: removeList,
- }, nil
-
-}
-
-type MedAction struct {
- value int64
- action MedActionType
-}
-
-func (a *MedAction) Type() ActionType {
- return ACTION_MED
-}
-
-func (a *MedAction) Apply(path *Path, _ *PolicyOptions) *Path {
- var err error
- switch a.action {
- case MED_ACTION_MOD:
- err = path.SetMed(a.value, false)
- case MED_ACTION_REPLACE:
- err = path.SetMed(a.value, true)
- }
-
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "Med Action",
- "Error": err,
- }).Warn("Could not set Med on path")
- }
- return path
-}
-
-func (a *MedAction) ToConfig() config.BgpSetMedType {
- if a.action == MED_ACTION_MOD && a.value > 0 {
- return config.BgpSetMedType(fmt.Sprintf("+%d", a.value))
- }
- return config.BgpSetMedType(fmt.Sprintf("%d", a.value))
-}
-
-func (a *MedAction) String() string {
- return string(a.ToConfig())
-}
-
-func (a *MedAction) MarshalJSON() ([]byte, error) {
- return json.Marshal(a.ToConfig())
-}
-
-var _regexpParseMedAction = regexp.MustCompile(`^(\+|\-)?(\d+)$`)
-
-func NewMedAction(c config.BgpSetMedType) (*MedAction, error) {
- if string(c) == "" {
- return nil, nil
- }
-
- elems := _regexpParseMedAction.FindStringSubmatch(string(c))
- if len(elems) != 3 {
- return nil, fmt.Errorf("invalid med action format")
- }
- action := MED_ACTION_REPLACE
- switch elems[1] {
- case "+", "-":
- action = MED_ACTION_MOD
- }
- value, _ := strconv.ParseInt(string(c), 10, 64)
- return &MedAction{
- value: value,
- action: action,
- }, nil
-}
-
-func NewMedActionFromApiStruct(action MedActionType, value int64) *MedAction {
- return &MedAction{action: action, value: value}
-}
-
-type LocalPrefAction struct {
- value uint32
-}
-
-func (a *LocalPrefAction) Type() ActionType {
- return ACTION_LOCAL_PREF
-}
-
-func (a *LocalPrefAction) Apply(path *Path, _ *PolicyOptions) *Path {
- path.setPathAttr(bgp.NewPathAttributeLocalPref(a.value))
- return path
-}
-
-func (a *LocalPrefAction) ToConfig() uint32 {
- return a.value
-}
-
-func (a *LocalPrefAction) String() string {
- return fmt.Sprintf("%d", a.value)
-}
-
-func (a *LocalPrefAction) MarshalJSON() ([]byte, error) {
- return json.Marshal(a.ToConfig())
-}
-
-func NewLocalPrefAction(value uint32) (*LocalPrefAction, error) {
- if value == 0 {
- return nil, nil
- }
- return &LocalPrefAction{
- value: value,
- }, nil
-}
-
-type AsPathPrependAction struct {
- asn uint32
- useLeftMost bool
- repeat uint8
-}
-
-func (a *AsPathPrependAction) Type() ActionType {
- return ACTION_AS_PATH_PREPEND
-}
-
-func (a *AsPathPrependAction) Apply(path *Path, option *PolicyOptions) *Path {
- var asn uint32
- if a.useLeftMost {
- aspath := path.GetAsSeqList()
- if len(aspath) == 0 {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "AsPathPrepend Action",
- }).Warn("aspath length is zero.")
- return path
- }
- asn = aspath[0]
- if asn == 0 {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Type": "AsPathPrepend Action",
- }).Warn("left-most ASN is not seq")
- return path
- }
- } else {
- asn = a.asn
- }
-
- confed := option != nil && option.Info.Confederation
- path.PrependAsn(asn, a.repeat, confed)
-
- return path
-}
-
-func (a *AsPathPrependAction) ToConfig() *config.SetAsPathPrepend {
- return &config.SetAsPathPrepend{
- RepeatN: uint8(a.repeat),
- As: func() string {
- if a.useLeftMost {
- return "last-as"
- }
- return fmt.Sprintf("%d", a.asn)
- }(),
- }
-}
-
-func (a *AsPathPrependAction) String() string {
- c := a.ToConfig()
- return fmt.Sprintf("prepend %s %d times", c.As, c.RepeatN)
-}
-
-func (a *AsPathPrependAction) MarshalJSON() ([]byte, error) {
- return json.Marshal(a.ToConfig())
-}
-
-// NewAsPathPrependAction creates AsPathPrependAction object.
-// If ASN cannot be parsed, nil will be returned.
-func NewAsPathPrependAction(action config.SetAsPathPrepend) (*AsPathPrependAction, error) {
- a := &AsPathPrependAction{
- repeat: action.RepeatN,
- }
- switch action.As {
- case "":
- if a.repeat == 0 {
- return nil, nil
- }
- return nil, fmt.Errorf("specify as to prepend")
- case "last-as":
- a.useLeftMost = true
- default:
- asn, err := strconv.ParseUint(action.As, 10, 32)
- if err != nil {
- return nil, fmt.Errorf("As number string invalid")
- }
- a.asn = uint32(asn)
- }
- return a, nil
-}
-
-type NexthopAction struct {
- value net.IP
- self bool
-}
-
-func (a *NexthopAction) Type() ActionType {
- return ACTION_NEXTHOP
-}
-
-func (a *NexthopAction) Apply(path *Path, options *PolicyOptions) *Path {
- if a.self {
- if options != nil && options.Info != nil && options.Info.LocalAddress != nil {
- path.SetNexthop(options.Info.LocalAddress)
- }
- return path
- }
- path.SetNexthop(a.value)
- return path
-}
-
-func (a *NexthopAction) ToConfig() config.BgpNextHopType {
- if a.self {
- return config.BgpNextHopType("self")
- }
- return config.BgpNextHopType(a.value.String())
-}
-
-func (a *NexthopAction) String() string {
- return string(a.ToConfig())
-}
-
-func (a *NexthopAction) MarshalJSON() ([]byte, error) {
- return json.Marshal(a.ToConfig())
-}
-
-func NewNexthopAction(c config.BgpNextHopType) (*NexthopAction, error) {
- switch strings.ToLower(string(c)) {
- case "":
- return nil, nil
- case "self":
- return &NexthopAction{
- self: true,
- }, nil
- }
- addr := net.ParseIP(string(c))
- if addr == nil {
- return nil, fmt.Errorf("invalid ip address format: %s", string(c))
- }
- return &NexthopAction{
- value: addr,
- }, nil
-}
-
-type Statement struct {
- Name string
- Conditions []Condition
- RouteAction Action
- ModActions []Action
-}
-
-// evaluate each condition in the statement according to MatchSetOptions
-func (s *Statement) Evaluate(p *Path, options *PolicyOptions) bool {
- for _, c := range s.Conditions {
- if !c.Evaluate(p, options) {
- return false
- }
- }
- return true
-}
-
-func (s *Statement) Apply(path *Path, options *PolicyOptions) (RouteType, *Path) {
- result := s.Evaluate(path, options)
- if result {
- if len(s.ModActions) != 0 {
- // apply all modification actions
- path = path.Clone(path.IsWithdraw)
- for _, action := range s.ModActions {
- path = action.Apply(path, options)
- }
- }
- //Routing action
- if s.RouteAction == nil || reflect.ValueOf(s.RouteAction).IsNil() {
- return ROUTE_TYPE_NONE, path
- }
- p := s.RouteAction.Apply(path, options)
- if p == nil {
- return ROUTE_TYPE_REJECT, path
- }
- return ROUTE_TYPE_ACCEPT, path
- }
- return ROUTE_TYPE_NONE, path
-}
-
-func (s *Statement) ToConfig() *config.Statement {
- return &config.Statement{
- Name: s.Name,
- Conditions: func() config.Conditions {
- cond := config.Conditions{}
- for _, c := range s.Conditions {
- switch c.(type) {
- case *PrefixCondition:
- v := c.(*PrefixCondition)
- cond.MatchPrefixSet = config.MatchPrefixSet{PrefixSet: v.set.Name(), MatchSetOptions: v.option.ConvertToMatchSetOptionsRestrictedType()}
- case *NeighborCondition:
- v := c.(*NeighborCondition)
- cond.MatchNeighborSet = config.MatchNeighborSet{NeighborSet: v.set.Name(), MatchSetOptions: v.option.ConvertToMatchSetOptionsRestrictedType()}
- case *AsPathLengthCondition:
- v := c.(*AsPathLengthCondition)
- cond.BgpConditions.AsPathLength = config.AsPathLength{Operator: config.IntToAttributeComparisonMap[int(v.operator)], Value: v.length}
- case *AsPathCondition:
- v := c.(*AsPathCondition)
- cond.BgpConditions.MatchAsPathSet = config.MatchAsPathSet{AsPathSet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
- case *CommunityCondition:
- v := c.(*CommunityCondition)
- cond.BgpConditions.MatchCommunitySet = config.MatchCommunitySet{CommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
- case *ExtCommunityCondition:
- v := c.(*ExtCommunityCondition)
- cond.BgpConditions.MatchExtCommunitySet = config.MatchExtCommunitySet{ExtCommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
- case *LargeCommunityCondition:
- v := c.(*LargeCommunityCondition)
- cond.BgpConditions.MatchLargeCommunitySet = config.MatchLargeCommunitySet{LargeCommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
- case *NextHopCondition:
- v := c.(*NextHopCondition)
- cond.BgpConditions.NextHopInList = v.set.List()
- case *RpkiValidationCondition:
- v := c.(*RpkiValidationCondition)
- cond.BgpConditions.RpkiValidationResult = v.result
- case *RouteTypeCondition:
- v := c.(*RouteTypeCondition)
- cond.BgpConditions.RouteType = v.typ
- case *AfiSafiInCondition:
- v := c.(*AfiSafiInCondition)
- res := make([]config.AfiSafiType, 0, len(v.routeFamilies))
- for _, rf := range v.routeFamilies {
- res = append(res, config.AfiSafiType(rf.String()))
- }
- cond.BgpConditions.AfiSafiInList = res
- }
- }
- return cond
- }(),
- Actions: func() config.Actions {
- act := config.Actions{}
- if s.RouteAction != nil && !reflect.ValueOf(s.RouteAction).IsNil() {
- a := s.RouteAction.(*RoutingAction)
- if a.AcceptRoute {
- act.RouteDisposition = config.ROUTE_DISPOSITION_ACCEPT_ROUTE
- } else {
- act.RouteDisposition = config.ROUTE_DISPOSITION_REJECT_ROUTE
- }
- } else {
- act.RouteDisposition = config.ROUTE_DISPOSITION_NONE
- }
- for _, a := range s.ModActions {
- switch a.(type) {
- case *AsPathPrependAction:
- act.BgpActions.SetAsPathPrepend = *a.(*AsPathPrependAction).ToConfig()
- case *CommunityAction:
- act.BgpActions.SetCommunity = *a.(*CommunityAction).ToConfig()
- case *ExtCommunityAction:
- act.BgpActions.SetExtCommunity = *a.(*ExtCommunityAction).ToConfig()
- case *LargeCommunityAction:
- act.BgpActions.SetLargeCommunity = *a.(*LargeCommunityAction).ToConfig()
- case *MedAction:
- act.BgpActions.SetMed = a.(*MedAction).ToConfig()
- case *LocalPrefAction:
- act.BgpActions.SetLocalPref = a.(*LocalPrefAction).ToConfig()
- case *NexthopAction:
- act.BgpActions.SetNextHop = a.(*NexthopAction).ToConfig()
- }
- }
- return act
- }(),
- }
-}
-
-func (s *Statement) MarshalJSON() ([]byte, error) {
- return json.Marshal(s.ToConfig())
-}
-
-type opType int
-
-const (
- ADD opType = iota
- REMOVE
- REPLACE
-)
-
-func (lhs *Statement) mod(op opType, rhs *Statement) error {
- cs := make([]Condition, len(lhs.Conditions))
- copy(cs, lhs.Conditions)
- ra := lhs.RouteAction
- as := make([]Action, len(lhs.ModActions))
- copy(as, lhs.ModActions)
- for _, x := range rhs.Conditions {
- var c Condition
- i := 0
- for idx, y := range lhs.Conditions {
- if x.Type() == y.Type() {
- c = y
- i = idx
- break
- }
- }
- switch op {
- case ADD:
- if c != nil {
- return fmt.Errorf("condition %d is already set", x.Type())
- }
- if cs == nil {
- cs = make([]Condition, 0, len(rhs.Conditions))
- }
- cs = append(cs, x)
- case REMOVE:
- if c == nil {
- return fmt.Errorf("condition %d is not set", x.Type())
- }
- cs = append(cs[:i], cs[i+1:]...)
- if len(cs) == 0 {
- cs = nil
- }
- case REPLACE:
- if c == nil {
- return fmt.Errorf("condition %d is not set", x.Type())
- }
- cs[i] = x
- }
- }
- if rhs.RouteAction != nil && !reflect.ValueOf(rhs.RouteAction).IsNil() {
- switch op {
- case ADD:
- if lhs.RouteAction != nil && !reflect.ValueOf(lhs.RouteAction).IsNil() {
- return fmt.Errorf("route action is already set")
- }
- ra = rhs.RouteAction
- case REMOVE:
- if lhs.RouteAction == nil || reflect.ValueOf(lhs.RouteAction).IsNil() {
- return fmt.Errorf("route action is not set")
- }
- ra = nil
- case REPLACE:
- if lhs.RouteAction == nil || reflect.ValueOf(lhs.RouteAction).IsNil() {
- return fmt.Errorf("route action is not set")
- }
- ra = rhs.RouteAction
- }
- }
- for _, x := range rhs.ModActions {
- var a Action
- i := 0
- for idx, y := range lhs.ModActions {
- if x.Type() == y.Type() {
- a = y
- i = idx
- break
- }
- }
- switch op {
- case ADD:
- if a != nil {
- return fmt.Errorf("action %d is already set", x.Type())
- }
- if as == nil {
- as = make([]Action, 0, len(rhs.ModActions))
- }
- as = append(as, x)
- case REMOVE:
- if a == nil {
- return fmt.Errorf("action %d is not set", x.Type())
- }
- as = append(as[:i], as[i+1:]...)
- if len(as) == 0 {
- as = nil
- }
- case REPLACE:
- if a == nil {
- return fmt.Errorf("action %d is not set", x.Type())
- }
- as[i] = x
- }
- }
- lhs.Conditions = cs
- lhs.RouteAction = ra
- lhs.ModActions = as
- return nil
-}
-
-func (lhs *Statement) Add(rhs *Statement) error {
- return lhs.mod(ADD, rhs)
-}
-
-func (lhs *Statement) Remove(rhs *Statement) error {
- return lhs.mod(REMOVE, rhs)
-}
-
-func (lhs *Statement) Replace(rhs *Statement) error {
- return lhs.mod(REPLACE, rhs)
-}
-
-func NewStatement(c config.Statement) (*Statement, error) {
- if c.Name == "" {
- return nil, fmt.Errorf("empty statement name")
- }
- var ra Action
- var as []Action
- var cs []Condition
- var err error
- cfs := []func() (Condition, error){
- func() (Condition, error) {
- return NewPrefixCondition(c.Conditions.MatchPrefixSet)
- },
- func() (Condition, error) {
- return NewNeighborCondition(c.Conditions.MatchNeighborSet)
- },
- func() (Condition, error) {
- return NewAsPathLengthCondition(c.Conditions.BgpConditions.AsPathLength)
- },
- func() (Condition, error) {
- return NewRpkiValidationCondition(c.Conditions.BgpConditions.RpkiValidationResult)
- },
- func() (Condition, error) {
- return NewRouteTypeCondition(c.Conditions.BgpConditions.RouteType)
- },
- func() (Condition, error) {
- return NewAsPathCondition(c.Conditions.BgpConditions.MatchAsPathSet)
- },
- func() (Condition, error) {
- return NewCommunityCondition(c.Conditions.BgpConditions.MatchCommunitySet)
- },
- func() (Condition, error) {
- return NewExtCommunityCondition(c.Conditions.BgpConditions.MatchExtCommunitySet)
- },
- func() (Condition, error) {
- return NewLargeCommunityCondition(c.Conditions.BgpConditions.MatchLargeCommunitySet)
- },
- func() (Condition, error) {
- return NewNextHopCondition(c.Conditions.BgpConditions.NextHopInList)
- },
- func() (Condition, error) {
- return NewAfiSafiInCondition(c.Conditions.BgpConditions.AfiSafiInList)
- },
- }
- cs = make([]Condition, 0, len(cfs))
- for _, f := range cfs {
- c, err := f()
- if err != nil {
- return nil, err
- }
- if !reflect.ValueOf(c).IsNil() {
- cs = append(cs, c)
- }
- }
- ra, err = NewRoutingAction(c.Actions.RouteDisposition)
- if err != nil {
- return nil, err
- }
- afs := []func() (Action, error){
- func() (Action, error) {
- return NewCommunityAction(c.Actions.BgpActions.SetCommunity)
- },
- func() (Action, error) {
- return NewExtCommunityAction(c.Actions.BgpActions.SetExtCommunity)
- },
- func() (Action, error) {
- return NewLargeCommunityAction(c.Actions.BgpActions.SetLargeCommunity)
- },
- func() (Action, error) {
- return NewMedAction(c.Actions.BgpActions.SetMed)
- },
- func() (Action, error) {
- return NewLocalPrefAction(c.Actions.BgpActions.SetLocalPref)
- },
- func() (Action, error) {
- return NewAsPathPrependAction(c.Actions.BgpActions.SetAsPathPrepend)
- },
- func() (Action, error) {
- return NewNexthopAction(c.Actions.BgpActions.SetNextHop)
- },
- }
- as = make([]Action, 0, len(afs))
- for _, f := range afs {
- a, err := f()
- if err != nil {
- return nil, err
- }
- if !reflect.ValueOf(a).IsNil() {
- as = append(as, a)
- }
- }
- return &Statement{
- Name: c.Name,
- Conditions: cs,
- RouteAction: ra,
- ModActions: as,
- }, nil
-}
-
-type Policy struct {
- Name string
- Statements []*Statement
-}
-
-// Compare path with a policy's condition in stored order in the policy.
-// If a condition match, then this function stops evaluation and
-// subsequent conditions are skipped.
-func (p *Policy) Apply(path *Path, options *PolicyOptions) (RouteType, *Path) {
- for _, stmt := range p.Statements {
- var result RouteType
- result, path = stmt.Apply(path, options)
- if result != ROUTE_TYPE_NONE {
- return result, path
- }
- }
- return ROUTE_TYPE_NONE, path
-}
-
-func (p *Policy) ToConfig() *config.PolicyDefinition {
- ss := make([]config.Statement, 0, len(p.Statements))
- for _, s := range p.Statements {
- ss = append(ss, *s.ToConfig())
- }
- return &config.PolicyDefinition{
- Name: p.Name,
- Statements: ss,
- }
-}
-
-func (p *Policy) FillUp(m map[string]*Statement) error {
- stmts := make([]*Statement, 0, len(p.Statements))
- for _, x := range p.Statements {
- y, ok := m[x.Name]
- if !ok {
- return fmt.Errorf("not found statement %s", x.Name)
- }
- stmts = append(stmts, y)
- }
- p.Statements = stmts
- return nil
-}
-
-func (lhs *Policy) Add(rhs *Policy) error {
- lhs.Statements = append(lhs.Statements, rhs.Statements...)
- return nil
-}
-
-func (lhs *Policy) Remove(rhs *Policy) error {
- stmts := make([]*Statement, 0, len(lhs.Statements))
- for _, x := range lhs.Statements {
- found := false
- for _, y := range rhs.Statements {
- if x.Name == y.Name {
- found = true
- break
- }
- }
- if !found {
- stmts = append(stmts, x)
- }
- }
- lhs.Statements = stmts
- return nil
-}
-
-func (lhs *Policy) Replace(rhs *Policy) error {
- lhs.Statements = rhs.Statements
- return nil
-}
-
-func (p *Policy) MarshalJSON() ([]byte, error) {
- return json.Marshal(p.ToConfig())
-}
-
-func NewPolicy(c config.PolicyDefinition) (*Policy, error) {
- if c.Name == "" {
- return nil, fmt.Errorf("empty policy name")
- }
- var st []*Statement
- stmts := c.Statements
- if len(stmts) != 0 {
- st = make([]*Statement, 0, len(stmts))
- for idx, stmt := range stmts {
- if stmt.Name == "" {
- stmt.Name = fmt.Sprintf("%s_stmt%d", c.Name, idx)
- }
- s, err := NewStatement(stmt)
- if err != nil {
- return nil, err
- }
- st = append(st, s)
- }
- }
- return &Policy{
- Name: c.Name,
- Statements: st,
- }, nil
-}
-
-type Policies []*Policy
-
-func (p Policies) Len() int {
- return len(p)
-}
-
-func (p Policies) Swap(i, j int) {
- p[i], p[j] = p[j], p[i]
-}
-
-func (p Policies) Less(i, j int) bool {
- return p[i].Name < p[j].Name
-}
-
-type Assignment struct {
- inPolicies []*Policy
- defaultInPolicy RouteType
- importPolicies []*Policy
- defaultImportPolicy RouteType
- exportPolicies []*Policy
- defaultExportPolicy RouteType
-}
-
-type RoutingPolicy struct {
- definedSetMap DefinedSetMap
- policyMap map[string]*Policy
- statementMap map[string]*Statement
- assignmentMap map[string]*Assignment
- mu sync.RWMutex
-}
-
-func (r *RoutingPolicy) ApplyPolicy(id string, dir PolicyDirection, before *Path, options *PolicyOptions) *Path {
- r.mu.RLock()
- defer r.mu.RUnlock()
-
- if before == nil {
- return nil
- }
-
- if before.IsWithdraw {
- return before
- }
- result := ROUTE_TYPE_NONE
- after := before
- for _, p := range r.getPolicy(id, dir) {
- result, after = p.Apply(after, options)
- if result != ROUTE_TYPE_NONE {
- break
- }
- }
- if result == ROUTE_TYPE_NONE {
- result = r.getDefaultPolicy(id, dir)
- }
- switch result {
- case ROUTE_TYPE_ACCEPT:
- return after
- default:
- return nil
- }
-}
-
-func (r *RoutingPolicy) getPolicy(id string, dir PolicyDirection) []*Policy {
- a, ok := r.assignmentMap[id]
- if !ok {
- return nil
- }
- switch dir {
- case POLICY_DIRECTION_IN:
- return a.inPolicies
- case POLICY_DIRECTION_IMPORT:
- return a.importPolicies
- case POLICY_DIRECTION_EXPORT:
- return a.exportPolicies
- default:
- return nil
- }
-}
-
-func (r *RoutingPolicy) getDefaultPolicy(id string, dir PolicyDirection) RouteType {
- a, ok := r.assignmentMap[id]
- if !ok {
- return ROUTE_TYPE_NONE
- }
- switch dir {
- case POLICY_DIRECTION_IN:
- return a.defaultInPolicy
- case POLICY_DIRECTION_IMPORT:
- return a.defaultImportPolicy
- case POLICY_DIRECTION_EXPORT:
- return a.defaultExportPolicy
- default:
- return ROUTE_TYPE_NONE
- }
-
-}
-
-func (r *RoutingPolicy) setPolicy(id string, dir PolicyDirection, policies []*Policy) error {
- a, ok := r.assignmentMap[id]
- if !ok {
- a = &Assignment{}
- }
- switch dir {
- case POLICY_DIRECTION_IN:
- a.inPolicies = policies
- case POLICY_DIRECTION_IMPORT:
- a.importPolicies = policies
- case POLICY_DIRECTION_EXPORT:
- a.exportPolicies = policies
- }
- r.assignmentMap[id] = a
- return nil
-}
-
-func (r *RoutingPolicy) setDefaultPolicy(id string, dir PolicyDirection, typ RouteType) error {
- a, ok := r.assignmentMap[id]
- if !ok {
- a = &Assignment{}
- }
- switch dir {
- case POLICY_DIRECTION_IN:
- a.defaultInPolicy = typ
- case POLICY_DIRECTION_IMPORT:
- a.defaultImportPolicy = typ
- case POLICY_DIRECTION_EXPORT:
- a.defaultExportPolicy = typ
- }
- r.assignmentMap[id] = a
- return nil
-}
-
-func (r *RoutingPolicy) getAssignmentFromConfig(dir PolicyDirection, a config.ApplyPolicy) ([]*Policy, RouteType, error) {
- var names []string
- var cdef config.DefaultPolicyType
- def := ROUTE_TYPE_ACCEPT
- c := a.Config
- switch dir {
- case POLICY_DIRECTION_IN:
- names = c.InPolicyList
- cdef = c.DefaultInPolicy
- case POLICY_DIRECTION_IMPORT:
- names = c.ImportPolicyList
- cdef = c.DefaultImportPolicy
- case POLICY_DIRECTION_EXPORT:
- names = c.ExportPolicyList
- cdef = c.DefaultExportPolicy
- default:
- return nil, def, fmt.Errorf("invalid policy direction")
- }
- if cdef == config.DEFAULT_POLICY_TYPE_REJECT_ROUTE {
- def = ROUTE_TYPE_REJECT
- }
- ps := make([]*Policy, 0, len(names))
- seen := make(map[string]bool)
- for _, name := range names {
- p, ok := r.policyMap[name]
- if !ok {
- return nil, def, fmt.Errorf("not found policy %s", name)
- }
- if seen[name] {
- return nil, def, fmt.Errorf("duplicated policy %s", name)
- }
- seen[name] = true
- ps = append(ps, p)
- }
- return ps, def, nil
-}
-
-func (r *RoutingPolicy) validateCondition(v Condition) (err error) {
- switch v.Type() {
- case CONDITION_PREFIX:
- m := r.definedSetMap[DEFINED_TYPE_PREFIX]
- if i, ok := m[v.Name()]; !ok {
- return fmt.Errorf("not found prefix set %s", v.Name())
- } else {
- c := v.(*PrefixCondition)
- c.set = i.(*PrefixSet)
- }
- case CONDITION_NEIGHBOR:
- m := r.definedSetMap[DEFINED_TYPE_NEIGHBOR]
- if i, ok := m[v.Name()]; !ok {
- return fmt.Errorf("not found neighbor set %s", v.Name())
- } else {
- c := v.(*NeighborCondition)
- c.set = i.(*NeighborSet)
- }
- case CONDITION_AS_PATH:
- m := r.definedSetMap[DEFINED_TYPE_AS_PATH]
- if i, ok := m[v.Name()]; !ok {
- return fmt.Errorf("not found as path set %s", v.Name())
- } else {
- c := v.(*AsPathCondition)
- c.set = i.(*AsPathSet)
- }
- case CONDITION_COMMUNITY:
- m := r.definedSetMap[DEFINED_TYPE_COMMUNITY]
- if i, ok := m[v.Name()]; !ok {
- return fmt.Errorf("not found community set %s", v.Name())
- } else {
- c := v.(*CommunityCondition)
- c.set = i.(*CommunitySet)
- }
- case CONDITION_EXT_COMMUNITY:
- m := r.definedSetMap[DEFINED_TYPE_EXT_COMMUNITY]
- if i, ok := m[v.Name()]; !ok {
- return fmt.Errorf("not found ext-community set %s", v.Name())
- } else {
- c := v.(*ExtCommunityCondition)
- c.set = i.(*ExtCommunitySet)
- }
- case CONDITION_LARGE_COMMUNITY:
- m := r.definedSetMap[DEFINED_TYPE_LARGE_COMMUNITY]
- if i, ok := m[v.Name()]; !ok {
- return fmt.Errorf("not found large-community set %s", v.Name())
- } else {
- c := v.(*LargeCommunityCondition)
- c.set = i.(*LargeCommunitySet)
- }
- case CONDITION_NEXT_HOP:
- case CONDITION_AFI_SAFI_IN:
- case CONDITION_AS_PATH_LENGTH:
- case CONDITION_RPKI:
- }
- return nil
-}
-
-func (r *RoutingPolicy) inUse(d DefinedSet) bool {
- name := d.Name()
- for _, p := range r.policyMap {
- for _, s := range p.Statements {
- for _, c := range s.Conditions {
- if c.Set() != nil && c.Set().Name() == name {
- return true
- }
- }
- }
- }
- return false
-}
-
-func (r *RoutingPolicy) statementInUse(x *Statement) bool {
- for _, p := range r.policyMap {
- for _, y := range p.Statements {
- if x.Name == y.Name {
- return true
- }
- }
- }
- return false
-}
-
-func (r *RoutingPolicy) reload(c config.RoutingPolicy) error {
- dmap := make(map[DefinedType]map[string]DefinedSet)
- dmap[DEFINED_TYPE_PREFIX] = make(map[string]DefinedSet)
- d := c.DefinedSets
- for _, x := range d.PrefixSets {
- y, err := NewPrefixSet(x)
- if err != nil {
- return err
- }
- if y == nil {
- return fmt.Errorf("empty prefix set")
- }
- dmap[DEFINED_TYPE_PREFIX][y.Name()] = y
- }
- dmap[DEFINED_TYPE_NEIGHBOR] = make(map[string]DefinedSet)
- for _, x := range d.NeighborSets {
- y, err := NewNeighborSet(x)
- if err != nil {
- return err
- }
- if y == nil {
- return fmt.Errorf("empty neighbor set")
- }
- dmap[DEFINED_TYPE_NEIGHBOR][y.Name()] = y
- }
- // dmap[DEFINED_TYPE_TAG] = make(map[string]DefinedSet)
- // for _, x := range c.DefinedSets.TagSets{
- // y, err := NewTagSet(x)
- // if err != nil {
- // return nil, err
- // }
- // dmap[DEFINED_TYPE_TAG][y.Name()] = y
- // }
- bd := c.DefinedSets.BgpDefinedSets
- dmap[DEFINED_TYPE_AS_PATH] = make(map[string]DefinedSet)
- for _, x := range bd.AsPathSets {
- y, err := NewAsPathSet(x)
- if err != nil {
- return err
- }
- if y == nil {
- return fmt.Errorf("empty as path set")
- }
- dmap[DEFINED_TYPE_AS_PATH][y.Name()] = y
- }
- dmap[DEFINED_TYPE_COMMUNITY] = make(map[string]DefinedSet)
- for _, x := range bd.CommunitySets {
- y, err := NewCommunitySet(x)
- if err != nil {
- return err
- }
- if y == nil {
- return fmt.Errorf("empty community set")
- }
- dmap[DEFINED_TYPE_COMMUNITY][y.Name()] = y
- }
- dmap[DEFINED_TYPE_EXT_COMMUNITY] = make(map[string]DefinedSet)
- for _, x := range bd.ExtCommunitySets {
- y, err := NewExtCommunitySet(x)
- if err != nil {
- return err
- }
- if y == nil {
- return fmt.Errorf("empty ext-community set")
- }
- dmap[DEFINED_TYPE_EXT_COMMUNITY][y.Name()] = y
- }
- dmap[DEFINED_TYPE_LARGE_COMMUNITY] = make(map[string]DefinedSet)
- for _, x := range bd.LargeCommunitySets {
- y, err := NewLargeCommunitySet(x)
- if err != nil {
- return err
- }
- if y == nil {
- return fmt.Errorf("empty large-community set")
- }
- dmap[DEFINED_TYPE_LARGE_COMMUNITY][y.Name()] = y
- }
-
- pmap := make(map[string]*Policy)
- smap := make(map[string]*Statement)
- for _, x := range c.PolicyDefinitions {
- y, err := NewPolicy(x)
- if err != nil {
- return err
- }
- if _, ok := pmap[y.Name]; ok {
- return fmt.Errorf("duplicated policy name. policy name must be unique.")
- }
- pmap[y.Name] = y
- for _, s := range y.Statements {
- _, ok := smap[s.Name]
- if ok {
- return fmt.Errorf("duplicated statement name. statement name must be unique.")
- }
- smap[s.Name] = s
- }
- }
-
- // hacky
- oldMap := r.definedSetMap
- r.definedSetMap = dmap
- for _, y := range pmap {
- for _, s := range y.Statements {
- for _, c := range s.Conditions {
- if err := r.validateCondition(c); err != nil {
- r.definedSetMap = oldMap
- return err
- }
- }
- }
- }
-
- r.definedSetMap = dmap
- r.policyMap = pmap
- r.statementMap = smap
- r.assignmentMap = make(map[string]*Assignment)
- // allow all routes coming in and going out by default
- r.setDefaultPolicy(GLOBAL_RIB_NAME, POLICY_DIRECTION_IMPORT, ROUTE_TYPE_ACCEPT)
- r.setDefaultPolicy(GLOBAL_RIB_NAME, POLICY_DIRECTION_EXPORT, ROUTE_TYPE_ACCEPT)
- return nil
-}
-
-func (r *RoutingPolicy) GetDefinedSet(typ DefinedType, name string) (*config.DefinedSets, error) {
- r.mu.RLock()
-
- set, ok := r.definedSetMap[typ]
- if !ok {
- return nil, fmt.Errorf("invalid defined-set type: %d", typ)
- }
-
- var dl DefinedSetList
- for _, s := range set {
- dl = append(dl, s)
- }
- r.mu.RUnlock()
-
- sort.Sort(dl)
-
- sets := &config.DefinedSets{
- PrefixSets: make([]config.PrefixSet, 0),
- NeighborSets: make([]config.NeighborSet, 0),
- BgpDefinedSets: config.BgpDefinedSets{
- CommunitySets: make([]config.CommunitySet, 0),
- ExtCommunitySets: make([]config.ExtCommunitySet, 0),
- LargeCommunitySets: make([]config.LargeCommunitySet, 0),
- AsPathSets: make([]config.AsPathSet, 0),
- },
- }
- for _, s := range dl {
- if name != "" && s.Name() != name {
- continue
- }
- switch s.(type) {
- case *PrefixSet:
- sets.PrefixSets = append(sets.PrefixSets, *s.(*PrefixSet).ToConfig())
- case *NeighborSet:
- sets.NeighborSets = append(sets.NeighborSets, *s.(*NeighborSet).ToConfig())
- case *CommunitySet:
- sets.BgpDefinedSets.CommunitySets = append(sets.BgpDefinedSets.CommunitySets, *s.(*CommunitySet).ToConfig())
- case *ExtCommunitySet:
- sets.BgpDefinedSets.ExtCommunitySets = append(sets.BgpDefinedSets.ExtCommunitySets, *s.(*ExtCommunitySet).ToConfig())
- case *LargeCommunitySet:
- sets.BgpDefinedSets.LargeCommunitySets = append(sets.BgpDefinedSets.LargeCommunitySets, *s.(*LargeCommunitySet).ToConfig())
- case *AsPathSet:
- sets.BgpDefinedSets.AsPathSets = append(sets.BgpDefinedSets.AsPathSets, *s.(*AsPathSet).ToConfig())
- }
- }
- return sets, nil
-}
-
-func (r *RoutingPolicy) AddDefinedSet(s DefinedSet) error {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- if m, ok := r.definedSetMap[s.Type()]; !ok {
- return fmt.Errorf("invalid defined-set type: %d", s.Type())
- } else {
- if d, ok := m[s.Name()]; ok {
- if err := d.Append(s); err != nil {
- return err
- }
- } else {
- m[s.Name()] = s
- }
- }
- return nil
-}
-
-func (r *RoutingPolicy) DeleteDefinedSet(a DefinedSet, all bool) (err error) {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- if m, ok := r.definedSetMap[a.Type()]; !ok {
- err = fmt.Errorf("invalid defined-set type: %d", a.Type())
- } else {
- d, ok := m[a.Name()]
- if !ok {
- return fmt.Errorf("not found defined-set: %s", a.Name())
- }
- if all {
- if r.inUse(d) {
- err = fmt.Errorf("can't delete. defined-set %s is in use", a.Name())
- } else {
- delete(m, a.Name())
- }
- } else {
- err = d.Remove(a)
- }
- }
- return err
-}
-
-func (r *RoutingPolicy) ReplaceDefinedSet(a DefinedSet) (err error) {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- if m, ok := r.definedSetMap[a.Type()]; !ok {
- err = fmt.Errorf("invalid defined-set type: %d", a.Type())
- } else {
- if d, ok := m[a.Name()]; !ok {
- err = fmt.Errorf("not found defined-set: %s", a.Name())
- } else {
- err = d.Replace(a)
- }
- }
- return err
-}
-
-func (r *RoutingPolicy) GetStatement() []*config.Statement {
- r.mu.RLock()
- defer r.mu.RUnlock()
-
- l := make([]*config.Statement, 0, len(r.statementMap))
- for _, st := range r.statementMap {
- l = append(l, st.ToConfig())
- }
- return l
-}
-
-func (r *RoutingPolicy) AddStatement(st *Statement) (err error) {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- for _, c := range st.Conditions {
- if err = r.validateCondition(c); err != nil {
- return
- }
- }
- m := r.statementMap
- name := st.Name
- if d, ok := m[name]; ok {
- err = d.Add(st)
- } else {
- m[name] = st
- }
-
- return err
-}
-
-func (r *RoutingPolicy) DeleteStatement(st *Statement, all bool) (err error) {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- m := r.statementMap
- name := st.Name
- if d, ok := m[name]; ok {
- if all {
- if r.statementInUse(d) {
- err = fmt.Errorf("can't delete. statement %s is in use", name)
- } else {
- delete(m, name)
- }
- } else {
- err = d.Remove(st)
- }
- } else {
- err = fmt.Errorf("not found statement: %s", name)
- }
- return err
-}
-
-func (r *RoutingPolicy) ReplaceStatement(st *Statement) (err error) {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- for _, c := range st.Conditions {
- if err = r.validateCondition(c); err != nil {
- return
- }
- }
- m := r.statementMap
- name := st.Name
- if d, ok := m[name]; ok {
- err = d.Replace(st)
- } else {
- err = fmt.Errorf("not found statement: %s", name)
- }
- return err
-}
-
-func (r *RoutingPolicy) GetAllPolicy() []*config.PolicyDefinition {
- r.mu.RLock()
-
- var ps Policies
- for _, p := range r.policyMap {
- ps = append(ps, p)
- }
- r.mu.RUnlock()
-
- sort.Sort(ps)
-
- l := make([]*config.PolicyDefinition, 0, len(ps))
- for _, p := range ps {
- l = append(l, p.ToConfig())
- }
- return l
-}
-
-func (r *RoutingPolicy) AddPolicy(x *Policy, refer bool) (err error) {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- for _, st := range x.Statements {
- for _, c := range st.Conditions {
- if err = r.validateCondition(c); err != nil {
- return
- }
- }
- }
-
- pMap := r.policyMap
- sMap := r.statementMap
- name := x.Name
- y, ok := pMap[name]
- if refer {
- err = x.FillUp(sMap)
- } else {
- for _, st := range x.Statements {
- if _, ok := sMap[st.Name]; ok {
- err = fmt.Errorf("statement %s already defined", st.Name)
- return
- }
- sMap[st.Name] = st
- }
- }
- if ok {
- err = y.Add(x)
- } else {
- pMap[name] = x
- }
-
- return err
-}
-
-func (r *RoutingPolicy) DeletePolicy(x *Policy, all, preserve bool, activeId []string) (err error) {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- pMap := r.policyMap
- sMap := r.statementMap
- name := x.Name
- y, ok := pMap[name]
- if !ok {
- err = fmt.Errorf("not found policy: %s", name)
- return
- }
- inUse := func(ids []string) bool {
- for _, id := range ids {
- for _, dir := range []PolicyDirection{POLICY_DIRECTION_IN, POLICY_DIRECTION_EXPORT, POLICY_DIRECTION_EXPORT} {
- for _, y := range r.getPolicy(id, dir) {
- if x.Name == y.Name {
- return true
- }
- }
- }
- }
- return false
- }
-
- if all {
- if inUse(activeId) {
- err = fmt.Errorf("can't delete. policy %s is in use", name)
- return
- }
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Key": name,
- }).Debug("delete policy")
- delete(pMap, name)
- } else {
- err = y.Remove(x)
- }
- if err == nil && !preserve {
- for _, st := range y.Statements {
- if !r.statementInUse(st) {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Key": st.Name,
- }).Debug("delete unused statement")
- delete(sMap, st.Name)
- }
- }
- }
- return err
-}
-
-func (r *RoutingPolicy) ReplacePolicy(x *Policy, refer, preserve bool) (err error) {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- for _, st := range x.Statements {
- for _, c := range st.Conditions {
- if err = r.validateCondition(c); err != nil {
- return
- }
- }
- }
-
- pMap := r.policyMap
- sMap := r.statementMap
- name := x.Name
- y, ok := pMap[name]
- if !ok {
- err = fmt.Errorf("not found policy: %s", name)
- return
- }
- if refer {
- if err = x.FillUp(sMap); err != nil {
- return
- }
- } else {
- for _, st := range x.Statements {
- if _, ok := sMap[st.Name]; ok {
- err = fmt.Errorf("statement %s already defined", st.Name)
- return
- }
- sMap[st.Name] = st
- }
- }
-
- ys := y.Statements
- err = y.Replace(x)
- if err == nil && !preserve {
- for _, st := range ys {
- if !r.statementInUse(st) {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Key": st.Name,
- }).Debug("delete unused statement")
- delete(sMap, st.Name)
- }
- }
- }
- return err
-}
-
-func (r *RoutingPolicy) GetPolicyAssignment(id string, dir PolicyDirection) (RouteType, []*config.PolicyDefinition, error) {
- r.mu.RLock()
- defer r.mu.RUnlock()
-
- rt := r.getDefaultPolicy(id, dir)
-
- ps := r.getPolicy(id, dir)
- l := make([]*config.PolicyDefinition, 0, len(ps))
- for _, p := range ps {
- l = append(l, p.ToConfig())
- }
- return rt, l, nil
-}
-
-func (r *RoutingPolicy) AddPolicyAssignment(id string, dir PolicyDirection, policies []*config.PolicyDefinition, def RouteType) (err error) {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- ps := make([]*Policy, 0, len(policies))
- seen := make(map[string]bool)
- for _, x := range policies {
- p, ok := r.policyMap[x.Name]
- if !ok {
- err = fmt.Errorf("not found policy %s", x.Name)
- return
- }
- if seen[x.Name] {
- err = fmt.Errorf("duplicated policy %s", x.Name)
- return
- }
- seen[x.Name] = true
- ps = append(ps, p)
- }
- cur := r.getPolicy(id, dir)
- if cur == nil {
- err = r.setPolicy(id, dir, ps)
- } else {
- seen = make(map[string]bool)
- ps = append(cur, ps...)
- for _, x := range ps {
- if seen[x.Name] {
- err = fmt.Errorf("duplicated policy %s", x.Name)
- return
- }
- seen[x.Name] = true
- }
- err = r.setPolicy(id, dir, ps)
- }
- if err == nil && def != ROUTE_TYPE_NONE {
- err = r.setDefaultPolicy(id, dir, def)
- }
- return err
-}
-
-func (r *RoutingPolicy) DeletePolicyAssignment(id string, dir PolicyDirection, policies []*config.PolicyDefinition, all bool) (err error) {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- ps := make([]*Policy, 0, len(policies))
- seen := make(map[string]bool)
- for _, x := range policies {
- p, ok := r.policyMap[x.Name]
- if !ok {
- err = fmt.Errorf("not found policy %s", x.Name)
- return
- }
- if seen[x.Name] {
- err = fmt.Errorf("duplicated policy %s", x.Name)
- return
- }
- seen[x.Name] = true
- ps = append(ps, p)
- }
- cur := r.getPolicy(id, dir)
-
- if all {
- err = r.setPolicy(id, dir, nil)
- if err != nil {
- return
- }
- err = r.setDefaultPolicy(id, dir, ROUTE_TYPE_NONE)
- } else {
- l := len(cur) - len(ps)
- if l < 0 {
- // try to remove more than the assigned policies...
- l = len(cur)
- }
- n := make([]*Policy, 0, l)
- for _, y := range cur {
- found := false
- for _, x := range ps {
- if x.Name == y.Name {
- found = true
- break
- }
- }
- if !found {
- n = append(n, y)
- }
- }
- err = r.setPolicy(id, dir, n)
- }
- return err
-}
-
-func (r *RoutingPolicy) ReplacePolicyAssignment(id string, dir PolicyDirection, policies []*config.PolicyDefinition, def RouteType) (err error) {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- ps := make([]*Policy, 0, len(policies))
- seen := make(map[string]bool)
- for _, x := range policies {
- p, ok := r.policyMap[x.Name]
- if !ok {
- err = fmt.Errorf("not found policy %s", x.Name)
- return
- }
- if seen[x.Name] {
- err = fmt.Errorf("duplicated policy %s", x.Name)
- return
- }
- seen[x.Name] = true
- ps = append(ps, p)
- }
- r.getPolicy(id, dir)
- err = r.setPolicy(id, dir, ps)
- if err == nil && def != ROUTE_TYPE_NONE {
- err = r.setDefaultPolicy(id, dir, def)
- }
- return err
-}
-
-func (r *RoutingPolicy) Reset(rp *config.RoutingPolicy, ap map[string]config.ApplyPolicy) error {
- r.mu.Lock()
- defer r.mu.Unlock()
-
- if rp != nil {
- if err := r.reload(*rp); err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- }).Errorf("failed to create routing policy: %s", err)
- return err
- }
- }
-
- for id, c := range ap {
- for _, dir := range []PolicyDirection{POLICY_DIRECTION_IN, POLICY_DIRECTION_IMPORT, POLICY_DIRECTION_EXPORT} {
- ps, def, err := r.getAssignmentFromConfig(dir, c)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Policy",
- "Dir": dir,
- }).Errorf("failed to get policy info: %s", err)
- continue
- }
- r.setDefaultPolicy(id, dir, def)
- r.setPolicy(id, dir, ps)
- }
- }
- return nil
-}
-
-func NewRoutingPolicy() *RoutingPolicy {
- return &RoutingPolicy{
- definedSetMap: make(map[DefinedType]map[string]DefinedSet),
- policyMap: make(map[string]*Policy),
- statementMap: make(map[string]*Statement),
- assignmentMap: make(map[string]*Assignment),
- }
-}
-
-func CanImportToVrf(v *Vrf, path *Path) bool {
- f := func(arg []bgp.ExtendedCommunityInterface) []string {
- ret := make([]string, 0, len(arg))
- for _, a := range arg {
- ret = append(ret, fmt.Sprintf("RT:%s", a.String()))
- }
- return ret
- }
- set, _ := NewExtCommunitySet(config.ExtCommunitySet{
- ExtCommunitySetName: v.Name,
- ExtCommunityList: f(v.ImportRt),
- })
- matchSet := config.MatchExtCommunitySet{
- ExtCommunitySet: v.Name,
- MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY,
- }
- c, _ := NewExtCommunityCondition(matchSet)
- c.set = set
- return c.Evaluate(path, nil)
-}
-
-type PolicyAssignment struct {
- Name string
- Type PolicyDirection
- Policies []*Policy
- Default RouteType
-}
diff --git a/table/policy_test.go b/table/policy_test.go
deleted file mode 100644
index 858e1098..00000000
--- a/table/policy_test.go
+++ /dev/null
@@ -1,3140 +0,0 @@
-// 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/config"
- "github.com/osrg/gobgp/packet/bgp"
-
- log "github.com/sirupsen/logrus"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-func TestPrefixCalcurateNoRange(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.0")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // test
- pl1, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/24", MasklengthRange: ""})
- match1 := pl1.Match(path)
- assert.Equal(t, true, match1)
- pl2, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/23", MasklengthRange: ""})
- match2 := pl2.Match(path)
- assert.Equal(t, false, match2)
- pl3, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/16", MasklengthRange: "21..24"})
- match3 := pl3.Match(path)
- assert.Equal(t, true, match3)
-}
-
-func TestPrefixCalcurateAddress(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // test
- pl1, _ := NewPrefix(config.Prefix{IpPrefix: "10.11.0.0/16", MasklengthRange: "21..24"})
- match1 := pl1.Match(path)
- assert.Equal(t, false, match1)
- pl2, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/16", MasklengthRange: "21..24"})
- match2 := pl2.Match(path)
- assert.Equal(t, true, match2)
-}
-
-func TestPrefixCalcurateLength(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // test
- pl1, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.64.0/24", MasklengthRange: "21..24"})
- match1 := pl1.Match(path)
- assert.Equal(t, false, match1)
- pl2, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.64.0/16", MasklengthRange: "21..24"})
- match2 := pl2.Match(path)
- assert.Equal(t, true, match2)
-}
-
-func TestPrefixCalcurateLengthRange(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // test
- pl1, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/16", MasklengthRange: "21..23"})
- match1 := pl1.Match(path)
- assert.Equal(t, false, match1)
- pl2, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/16", MasklengthRange: "25..26"})
- match2 := pl2.Match(path)
- assert.Equal(t, false, match2)
- pl3, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/16", MasklengthRange: "21..24"})
- match3 := pl3.Match(path)
- assert.Equal(t, true, match3)
-}
-
-func TestPrefixCalcurateNoRangeIPv6(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("2001::192:168:50:1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- mpnlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")}
- mpreach := bgp.NewPathAttributeMpReachNLRI("2001::192:168:50:1", mpnlri)
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{mpreach, origin, aspath, med}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nil)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // test
- pl1, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123::/48", MasklengthRange: ""})
- match1 := pl1.Match(path)
- assert.Equal(t, false, match1)
- pl2, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123:1::/64", MasklengthRange: ""})
- match2 := pl2.Match(path)
- assert.Equal(t, true, match2)
- pl3, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123::/48", MasklengthRange: "64..80"})
- match3 := pl3.Match(path)
- assert.Equal(t, true, match3)
-}
-
-func TestPrefixCalcurateAddressIPv6(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("2001::192:168:50:1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- mpnlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")}
- mpreach := bgp.NewPathAttributeMpReachNLRI("2001::192:168:50:1", mpnlri)
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{mpreach, origin, aspath, med}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nil)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // test
- pl1, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:128::/48", MasklengthRange: "64..80"})
- match1 := pl1.Match(path)
- assert.Equal(t, false, match1)
- pl2, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123::/48", MasklengthRange: "64..80"})
- match2 := pl2.Match(path)
- assert.Equal(t, true, match2)
-}
-
-func TestPrefixCalcurateLengthIPv6(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("2001::192:168:50:1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- mpnlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")}
- mpreach := bgp.NewPathAttributeMpReachNLRI("2001::192:168:50:1", mpnlri)
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{mpreach, origin, aspath, med}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nil)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // test
- pl1, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123:64::/64", MasklengthRange: "64..80"})
- match1 := pl1.Match(path)
- assert.Equal(t, false, match1)
- pl2, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123:64::/48", MasklengthRange: "64..80"})
- match2 := pl2.Match(path)
- assert.Equal(t, true, match2)
-}
-
-func TestPrefixCalcurateLengthRangeIPv6(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("2001::192:168:50:1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- mpnlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")}
- mpreach := bgp.NewPathAttributeMpReachNLRI("2001::192:168:50:1", mpnlri)
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{mpreach, origin, aspath, med}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nil)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // test
- pl1, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123::/48", MasklengthRange: "62..63"})
- match1 := pl1.Match(path)
- assert.Equal(t, false, match1)
- pl2, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123::/48", MasklengthRange: "65..66"})
- match2 := pl2.Match(path)
- assert.Equal(t, false, match2)
- pl3, _ := NewPrefix(config.Prefix{IpPrefix: "2001:123:123::/48", MasklengthRange: "63..65"})
- match3 := pl3.Match(path)
- assert.Equal(t, true, match3)
-}
-
-func TestPolicyNotMatch(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- ps := createPrefixSet("ps1", "10.3.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
- s := createStatement("statement1", "ps1", "ns1", false)
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- pType, newPath := r.policyMap["pd1"].Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_NONE, pType)
- assert.Equal(t, newPath, path)
-}
-
-func TestPolicyMatchAndReject(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- s := createStatement("statement1", "ps1", "ns1", false)
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- pType, newPath := r.policyMap["pd1"].Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_REJECT, pType)
- assert.Equal(t, newPath, path)
-}
-
-func TestPolicyMatchAndAccept(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- s := createStatement("statement1", "ps1", "ns1", true)
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- pType, newPath := r.policyMap["pd1"].Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.Equal(t, path, newPath)
-}
-
-func TestPolicyRejectOnlyPrefixSet(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.1.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.1.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.1.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path1 := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- peer = &PeerInfo{AS: 65002, Address: net.ParseIP("10.0.2.2")}
- origin = bgp.NewPathAttributeOrigin(0)
- aspathParam = []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65002})}
- aspath = bgp.NewPathAttributeAsPath(aspathParam)
- nexthop = bgp.NewPathAttributeNextHop("10.0.2.2")
- med = bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes = []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri = []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.9.2.102")}
- updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path2 := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- ps := createPrefixSet("ps1", "10.10.1.0/16", "21..24")
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
-
- s := createStatement("statement1", "ps1", "", false)
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
- pType, newPath := p.Apply(path1, nil)
- assert.Equal(t, ROUTE_TYPE_REJECT, pType)
- assert.Equal(t, newPath, path1)
-
- pType2, newPath2 := p.Apply(path2, nil)
- assert.Equal(t, ROUTE_TYPE_NONE, pType2)
- assert.Equal(t, newPath2, path2)
-}
-
-func TestPolicyRejectOnlyNeighborSet(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.1.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.1.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.1.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path1 := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- peer = &PeerInfo{AS: 65002, Address: net.ParseIP("10.0.2.2")}
- origin = bgp.NewPathAttributeOrigin(0)
- aspathParam = []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65002})}
- aspath = bgp.NewPathAttributeAsPath(aspathParam)
- nexthop = bgp.NewPathAttributeNextHop("10.0.2.2")
- med = bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes = []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri = []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.2.102")}
- updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path2 := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- ns := createNeighborSet("ns1", "10.0.1.1")
- ds := config.DefinedSets{}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- s := createStatement("statement1", "", "ns1", false)
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- pType, newPath := r.policyMap["pd1"].Apply(path1, nil)
- assert.Equal(t, ROUTE_TYPE_REJECT, pType)
- assert.Equal(t, newPath, path1)
-
- pType2, newPath2 := r.policyMap["pd1"].Apply(path2, nil)
- assert.Equal(t, ROUTE_TYPE_NONE, pType2)
- assert.Equal(t, newPath2, path2)
-}
-
-func TestPolicyDifferentRoutefamilyOfPathAndPolicy(t *testing.T) {
- // create path ipv4
- peerIPv4 := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- originIPv4 := bgp.NewPathAttributeOrigin(0)
- aspathParamIPv4 := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspathIPv4 := bgp.NewPathAttributeAsPath(aspathParamIPv4)
- nexthopIPv4 := bgp.NewPathAttributeNextHop("10.0.0.1")
- medIPv4 := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributesIPv4 := []bgp.PathAttributeInterface{originIPv4, aspathIPv4, nexthopIPv4, medIPv4}
- nlriIPv4 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsgIPv4 := bgp.NewBGPUpdateMessage(nil, pathAttributesIPv4, nlriIPv4)
- pathIPv4 := ProcessMessage(updateMsgIPv4, peerIPv4, time.Now())[0]
- // create path ipv6
- peerIPv6 := &PeerInfo{AS: 65001, Address: net.ParseIP("2001::192:168:50:1")}
- originIPv6 := bgp.NewPathAttributeOrigin(0)
- aspathParamIPv6 := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspathIPv6 := bgp.NewPathAttributeAsPath(aspathParamIPv6)
- mpnlriIPv6 := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")}
- mpreachIPv6 := bgp.NewPathAttributeMpReachNLRI("2001::192:168:50:1", mpnlriIPv6)
- medIPv6 := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributesIPv6 := []bgp.PathAttributeInterface{mpreachIPv6, originIPv6, aspathIPv6, medIPv6}
- updateMsgIPv6 := bgp.NewBGPUpdateMessage(nil, pathAttributesIPv6, nil)
- pathIPv6 := ProcessMessage(updateMsgIPv6, peerIPv6, time.Now())[0]
- // create policy
- psIPv4 := createPrefixSet("psIPv4", "10.10.0.0/16", "21..24")
- nsIPv4 := createNeighborSet("nsIPv4", "10.0.0.1")
-
- psIPv6 := createPrefixSet("psIPv6", "2001:123:123::/48", "64..80")
- nsIPv6 := createNeighborSet("nsIPv6", "2001::192:168:50:1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{psIPv4, psIPv6}
- ds.NeighborSets = []config.NeighborSet{nsIPv4, nsIPv6}
-
- stIPv4 := createStatement("statement1", "psIPv4", "nsIPv4", false)
- stIPv6 := createStatement("statement2", "psIPv6", "nsIPv6", false)
-
- pd := createPolicyDefinition("pd1", stIPv4, stIPv6)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
- pType1, newPath1 := p.Apply(pathIPv4, nil)
- assert.Equal(t, ROUTE_TYPE_REJECT, pType1)
- assert.Equal(t, newPath1, pathIPv4)
-
- pType2, newPath2 := p.Apply(pathIPv6, nil)
- assert.Equal(t, ROUTE_TYPE_REJECT, pType2)
- assert.Equal(t, newPath2, pathIPv6)
-}
-
-func TestAsPathLengthConditionEvaluate(t *testing.T) {
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 65005}),
- bgp.NewAsPathParam(1, []uint16{65001, 65000, 65004, 65005}),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create match condition
- asPathLength := config.AsPathLength{
- Operator: "eq",
- Value: 5,
- }
- c, _ := NewAsPathLengthCondition(asPathLength)
-
- // test
- assert.Equal(t, true, c.Evaluate(path, nil))
-
- // create match condition
- asPathLength = config.AsPathLength{
- Operator: "ge",
- Value: 3,
- }
- c, _ = NewAsPathLengthCondition(asPathLength)
-
- // test
- assert.Equal(t, true, c.Evaluate(path, nil))
-
- // create match condition
- asPathLength = config.AsPathLength{
- Operator: "le",
- Value: 3,
- }
- c, _ = NewAsPathLengthCondition(asPathLength)
-
- // test
- assert.Equal(t, false, c.Evaluate(path, nil))
-}
-
-func TestPolicyMatchAndAcceptNextHop(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Conditions.BgpConditions.NextHopInList = []string{"10.0.0.1/32"}
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- pType, newPath := r.policyMap["pd1"].Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.Equal(t, newPath, path)
-}
-
-func TestPolicyMatchAndRejectNextHop(t *testing.T) {
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Conditions.BgpConditions.NextHopInList = []string{"10.0.0.12"}
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- pType, newPath := r.policyMap["pd1"].Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_NONE, pType)
- assert.Equal(t, newPath, path)
-}
-
-func TestAsPathLengthConditionWithOtherCondition(t *testing.T) {
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 65004, 65005}),
- bgp.NewAsPathParam(1, []uint16{65001, 65000, 65004, 65005}),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- ps := createPrefixSet("ps1", "10.10.1.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- // create match condition
- asPathLength := config.AsPathLength{
- Operator: "le",
- Value: 10,
- }
-
- s := createStatement("statement1", "ps1", "ns1", false)
- s.Conditions.BgpConditions.AsPathLength = asPathLength
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_REJECT, pType)
- assert.Equal(t, newPath, path)
-
-}
-
-func TestAs4PathLengthConditionEvaluate(t *testing.T) {
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- createAs4Value("65004.1"),
- createAs4Value("65005.1"),
- }),
- bgp.NewAs4PathParam(1, []uint32{
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- createAs4Value("65004.1"),
- createAs4Value("65005.1"),
- }),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create match condition
- asPathLength := config.AsPathLength{
- Operator: "eq",
- Value: 5,
- }
- c, _ := NewAsPathLengthCondition(asPathLength)
-
- // test
- assert.Equal(t, true, c.Evaluate(path, nil))
-
- // create match condition
- asPathLength = config.AsPathLength{
- Operator: "ge",
- Value: 3,
- }
- c, _ = NewAsPathLengthCondition(asPathLength)
-
- // test
- assert.Equal(t, true, c.Evaluate(path, nil))
-
- // create match condition
- asPathLength = config.AsPathLength{
- Operator: "le",
- Value: 3,
- }
- c, _ = NewAsPathLengthCondition(asPathLength)
-
- // test
- assert.Equal(t, false, c.Evaluate(path, nil))
-}
-
-func addPolicy(r *RoutingPolicy, x *Policy) {
- for _, s := range x.Statements {
- for _, c := range s.Conditions {
- r.validateCondition(c)
- }
- }
-}
-
-func TestAs4PathLengthConditionWithOtherCondition(t *testing.T) {
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- createAs4Value("65004.1"),
- createAs4Value("65004.1"),
- createAs4Value("65005.1"),
- }),
- bgp.NewAs4PathParam(1, []uint32{
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- createAs4Value("65004.1"),
- createAs4Value("65005.1"),
- }),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- ps := createPrefixSet("ps1", "10.10.1.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- // create match condition
- asPathLength := config.AsPathLength{
- Operator: "le",
- Value: 10,
- }
-
- s := createStatement("statement1", "ps1", "ns1", false)
- s.Conditions.BgpConditions.AsPathLength = asPathLength
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- r.reload(pl)
- p, _ := NewPolicy(pl.PolicyDefinitions[0])
- addPolicy(r, p)
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_REJECT, pType)
- assert.Equal(t, newPath, path)
-
-}
-
-func TestAsPathConditionEvaluate(t *testing.T) {
-
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam1 := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(2, []uint16{65001, 65000, 65010, 65004, 65005}),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam1)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate))
- path1 := ProcessMessage(updateMsg1, peer, time.Now())[0]
-
- aspathParam2 := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(2, []uint16{65010}),
- }
- aspath2 := bgp.NewPathAttributeAsPath(aspathParam2)
- pathAttributes = []bgp.PathAttributeInterface{origin, aspath2, nexthop, med}
- updateMsg2 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg2.Body.(*bgp.BGPUpdate))
- path2 := ProcessMessage(updateMsg2, peer, time.Now())[0]
-
- // create match condition
- asPathSet1 := config.AsPathSet{
- AsPathSetName: "asset1",
- AsPathList: []string{"^65001"},
- }
-
- asPathSet2 := config.AsPathSet{
- AsPathSetName: "asset2",
- AsPathList: []string{"65005$"},
- }
-
- asPathSet3 := config.AsPathSet{
- AsPathSetName: "asset3",
- AsPathList: []string{"65004", "65005$"},
- }
-
- asPathSet4 := config.AsPathSet{
- AsPathSetName: "asset4",
- AsPathList: []string{"65000$"},
- }
-
- asPathSet5 := config.AsPathSet{
- AsPathSetName: "asset5",
- AsPathList: []string{"65010"},
- }
-
- asPathSet6 := config.AsPathSet{
- AsPathSetName: "asset6",
- AsPathList: []string{"^65010$"},
- }
-
- m := make(map[string]DefinedSet)
- for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
- asPathSet4, asPathSet5, asPathSet6} {
- a, _ := NewAsPathSet(s)
- m[s.AsPathSetName] = a
- }
-
- createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition {
- matchSet := config.MatchAsPathSet{}
- matchSet.AsPathSet = name
- matchSet.MatchSetOptions = option
- p, _ := NewAsPathCondition(matchSet)
- if v, ok := m[name]; ok {
- p.set = v.(*AsPathSet)
- }
- return p
- }
-
- p1 := createAspathC("asset1", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p2 := createAspathC("asset2", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p3 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p4 := createAspathC("asset4", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p5 := createAspathC("asset5", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p6 := createAspathC("asset6", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p7 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ALL)
- p8 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_INVERT)
-
- // test
- assert.Equal(t, true, p1.Evaluate(path1, nil))
- assert.Equal(t, true, p2.Evaluate(path1, nil))
- assert.Equal(t, true, p3.Evaluate(path1, nil))
- assert.Equal(t, false, p4.Evaluate(path1, nil))
- assert.Equal(t, true, p5.Evaluate(path1, nil))
- assert.Equal(t, false, p6.Evaluate(path1, nil))
- assert.Equal(t, true, p6.Evaluate(path2, nil))
- assert.Equal(t, true, p7.Evaluate(path1, nil))
- assert.Equal(t, true, p8.Evaluate(path2, nil))
-}
-
-func TestMultipleAsPathConditionEvaluate(t *testing.T) {
-
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam1 := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(2, []uint16{65001, 65000, 54000, 65004, 65005}),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam1)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate))
- path1 := ProcessMessage(updateMsg1, peer, time.Now())[0]
-
- // create match condition
- asPathSet1 := config.AsPathSet{
- AsPathSetName: "asset1",
- AsPathList: []string{"^65001_65000"},
- }
-
- asPathSet2 := config.AsPathSet{
- AsPathSetName: "asset2",
- AsPathList: []string{"65004_65005$"},
- }
-
- asPathSet3 := config.AsPathSet{
- AsPathSetName: "asset3",
- AsPathList: []string{"65001_65000_54000"},
- }
-
- asPathSet4 := config.AsPathSet{
- AsPathSetName: "asset4",
- AsPathList: []string{"54000_65004_65005"},
- }
-
- asPathSet5 := config.AsPathSet{
- AsPathSetName: "asset5",
- AsPathList: []string{"^65001 65000 54000 65004 65005$"},
- }
-
- asPathSet6 := config.AsPathSet{
- AsPathSetName: "asset6",
- AsPathList: []string{".*_[0-9]+_65005"},
- }
-
- asPathSet7 := config.AsPathSet{
- AsPathSetName: "asset7",
- AsPathList: []string{".*_5[0-9]+_[0-9]+"},
- }
-
- asPathSet8 := config.AsPathSet{
- AsPathSetName: "asset8",
- AsPathList: []string{"6[0-9]+_6[0-9]+_5[0-9]+"},
- }
-
- asPathSet9 := config.AsPathSet{
- AsPathSetName: "asset9",
- AsPathList: []string{"6[0-9]+__6[0-9]+"},
- }
-
- m := make(map[string]DefinedSet)
- for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
- asPathSet4, asPathSet5, asPathSet6, asPathSet7, asPathSet8, asPathSet9} {
- a, _ := NewAsPathSet(s)
- m[s.AsPathSetName] = a
- }
-
- createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition {
- matchSet := config.MatchAsPathSet{}
- matchSet.AsPathSet = name
- matchSet.MatchSetOptions = option
- p, _ := NewAsPathCondition(matchSet)
- if v, ok := m[name]; ok {
- p.set = v.(*AsPathSet)
- }
- return p
- }
-
- p1 := createAspathC("asset1", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p2 := createAspathC("asset2", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p3 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p4 := createAspathC("asset4", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p5 := createAspathC("asset5", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p6 := createAspathC("asset6", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p7 := createAspathC("asset7", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p8 := createAspathC("asset8", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p9 := createAspathC("asset9", config.MATCH_SET_OPTIONS_TYPE_ANY)
-
- // test
- assert.Equal(t, true, p1.Evaluate(path1, nil))
- assert.Equal(t, true, p2.Evaluate(path1, nil))
- assert.Equal(t, true, p3.Evaluate(path1, nil))
- assert.Equal(t, true, p4.Evaluate(path1, nil))
- assert.Equal(t, true, p5.Evaluate(path1, nil))
- assert.Equal(t, true, p6.Evaluate(path1, nil))
- assert.Equal(t, true, p7.Evaluate(path1, nil))
- assert.Equal(t, true, p8.Evaluate(path1, nil))
- assert.Equal(t, false, p9.Evaluate(path1, nil))
-}
-
-func TestAsPathCondition(t *testing.T) {
- type astest struct {
- path *Path
- result bool
- }
-
- makeTest := func(asPathAttrType uint8, ases []uint32, result bool) astest {
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(asPathAttrType, ases),
- }
- pathAttributes := []bgp.PathAttributeInterface{bgp.NewPathAttributeAsPath(aspathParam)}
- p := NewPath(nil, nil, false, pathAttributes, time.Time{}, false)
- return astest{
- path: p,
- result: result,
- }
- }
-
- tests := make(map[string][]astest)
-
- tests["^(100_)+(200_)+$"] = []astest{
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{100, 200}, true),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{100, 100, 200}, true),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{100, 100, 200, 200}, true),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{100, 100, 200, 200, 300}, false),
- }
-
- aslen255 := func() []uint32 {
- r := make([]uint32, 255)
- for i := 0; i < 255; i++ {
- r[i] = 1
- }
- return r
- }()
- tests["^([0-9]+_){0,255}$"] = []astest{
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, aslen255, true),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, append(aslen255, 1), false),
- }
-
- tests["(_7521)$"] = []astest{
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{7521}, true),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{1000, 7521}, true),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{7521, 1000}, false),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{1000, 7521, 100}, false),
- }
-
- tests["^65001( |_.*_)65535$"] = []astest{
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65535}, true),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65001, 65535}, true),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65002, 65003, 65535}, true),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65534}, false),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65002, 65535}, false),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65002, 65001, 65535}, false),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65535, 65002}, false),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{650019, 65535}, false),
- makeTest(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 165535}, false),
- }
-
- for k, v := range tests {
- s, _ := NewAsPathSet(config.AsPathSet{
- AsPathSetName: k,
- AsPathList: []string{k},
- })
- c, _ := NewAsPathCondition(config.MatchAsPathSet{
- AsPathSet: k,
- MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY,
- })
- c.set = s
- for _, a := range v {
- result := c.Evaluate(a.path, nil)
- if a.result != result {
- log.WithFields(log.Fields{
- "EXP": k,
- "ASSTR": a.path.GetAsString(),
- "Expected": a.result,
- "Result": result,
- }).Fatal("failed")
- }
- }
- }
-}
-
-func TestAsPathConditionWithOtherCondition(t *testing.T) {
-
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(1, []uint16{65001, 65000, 65004, 65005}),
- bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 65004, 65005}),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- asPathSet := config.AsPathSet{
- AsPathSetName: "asset1",
- AsPathList: []string{"65005$"},
- }
-
- ps := createPrefixSet("ps1", "10.10.1.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
- ds.BgpDefinedSets.AsPathSets = []config.AsPathSet{asPathSet}
-
- s := createStatement("statement1", "ps1", "ns1", false)
- s.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = "asset1"
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_REJECT, pType)
- assert.Equal(t, newPath, path)
-
-}
-
-func TestAs4PathConditionEvaluate(t *testing.T) {
-
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam1 := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- createAs4Value("65010.1"),
- createAs4Value("65004.1"),
- createAs4Value("65005.1"),
- })}
-
- aspath := bgp.NewPathAttributeAsPath(aspathParam1)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate))
- path1 := ProcessMessage(updateMsg1, peer, time.Now())[0]
-
- aspathParam2 := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{
- createAs4Value("65010.1"),
- }),
- }
- aspath2 := bgp.NewPathAttributeAsPath(aspathParam2)
- pathAttributes = []bgp.PathAttributeInterface{origin, aspath2, nexthop, med}
- updateMsg2 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg2.Body.(*bgp.BGPUpdate))
- path2 := ProcessMessage(updateMsg2, peer, time.Now())[0]
-
- // create match condition
- asPathSet1 := config.AsPathSet{
- AsPathSetName: "asset1",
- AsPathList: []string{fmt.Sprintf("^%d", createAs4Value("65001.1"))},
- }
-
- asPathSet2 := config.AsPathSet{
- AsPathSetName: "asset2",
- AsPathList: []string{fmt.Sprintf("%d$", createAs4Value("65005.1"))},
- }
-
- asPathSet3 := config.AsPathSet{
- AsPathSetName: "asset3",
- AsPathList: []string{
- fmt.Sprintf("%d", createAs4Value("65004.1")),
- fmt.Sprintf("%d$", createAs4Value("65005.1")),
- },
- }
-
- asPathSet4 := config.AsPathSet{
- AsPathSetName: "asset4",
- AsPathList: []string{
- fmt.Sprintf("%d$", createAs4Value("65000.1")),
- },
- }
-
- asPathSet5 := config.AsPathSet{
- AsPathSetName: "asset5",
- AsPathList: []string{
- fmt.Sprintf("%d", createAs4Value("65010.1")),
- },
- }
-
- asPathSet6 := config.AsPathSet{
- AsPathSetName: "asset6",
- AsPathList: []string{
- fmt.Sprintf("%d$", createAs4Value("65010.1")),
- },
- }
-
- m := make(map[string]DefinedSet)
- for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
- asPathSet4, asPathSet5, asPathSet6} {
- a, _ := NewAsPathSet(s)
- m[s.AsPathSetName] = a
- }
-
- createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition {
- matchSet := config.MatchAsPathSet{}
- matchSet.AsPathSet = name
- matchSet.MatchSetOptions = option
- p, _ := NewAsPathCondition(matchSet)
- if v, ok := m[name]; ok {
- p.set = v.(*AsPathSet)
- }
- return p
- }
-
- p1 := createAspathC("asset1", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p2 := createAspathC("asset2", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p3 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p4 := createAspathC("asset4", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p5 := createAspathC("asset5", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p6 := createAspathC("asset6", config.MATCH_SET_OPTIONS_TYPE_ANY)
-
- p7 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ALL)
- p8 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_INVERT)
-
- // test
- assert.Equal(t, true, p1.Evaluate(path1, nil))
- assert.Equal(t, true, p2.Evaluate(path1, nil))
- assert.Equal(t, true, p3.Evaluate(path1, nil))
- assert.Equal(t, false, p4.Evaluate(path1, nil))
- assert.Equal(t, true, p5.Evaluate(path1, nil))
- assert.Equal(t, false, p6.Evaluate(path1, nil))
- assert.Equal(t, true, p6.Evaluate(path2, nil))
-
- assert.Equal(t, true, p7.Evaluate(path1, nil))
- assert.Equal(t, true, p8.Evaluate(path2, nil))
-}
-
-func TestMultipleAs4PathConditionEvaluate(t *testing.T) {
-
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam1 := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- createAs4Value("54000.1"),
- createAs4Value("65004.1"),
- createAs4Value("65005.1"),
- }),
- }
-
- aspath := bgp.NewPathAttributeAsPath(aspathParam1)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate))
- path1 := ProcessMessage(updateMsg1, peer, time.Now())[0]
-
- // create match condition
- asPathSet1 := config.AsPathSet{
- AsPathSetName: "asset1",
- AsPathList: []string{
- fmt.Sprintf("^%d_%d", createAs4Value("65001.1"), createAs4Value("65000.1")),
- },
- }
-
- asPathSet2 := config.AsPathSet{
- AsPathSetName: "asset2",
- AsPathList: []string{
- fmt.Sprintf("%d_%d$", createAs4Value("65004.1"), createAs4Value("65005.1")),
- },
- }
-
- asPathSet3 := config.AsPathSet{
- AsPathSetName: "asset3",
- AsPathList: []string{
- fmt.Sprintf("%d_%d_%d", createAs4Value("65001.1"), createAs4Value("65000.1"), createAs4Value("54000.1")),
- },
- }
-
- asPathSet4 := config.AsPathSet{
- AsPathSetName: "asset4",
- AsPathList: []string{
- fmt.Sprintf("%d_%d_%d", createAs4Value("54000.1"), createAs4Value("65004.1"), createAs4Value("65005.1")),
- },
- }
-
- asPathSet5 := config.AsPathSet{
- AsPathSetName: "asset5",
- AsPathList: []string{
- fmt.Sprintf("^%d %d %d %d %d$", createAs4Value("65001.1"), createAs4Value("65000.1"), createAs4Value("54000.1"), createAs4Value("65004.1"), createAs4Value("65005.1")),
- },
- }
-
- asPathSet6 := config.AsPathSet{
- AsPathSetName: "asset6",
- AsPathList: []string{
- fmt.Sprintf(".*_[0-9]+_%d", createAs4Value("65005.1")),
- },
- }
-
- asPathSet7 := config.AsPathSet{
- AsPathSetName: "asset7",
- AsPathList: []string{".*_3[0-9]+_[0-9]+"},
- }
-
- asPathSet8 := config.AsPathSet{
- AsPathSetName: "asset8",
- AsPathList: []string{"4[0-9]+_4[0-9]+_3[0-9]+"},
- }
-
- asPathSet9 := config.AsPathSet{
- AsPathSetName: "asset9",
- AsPathList: []string{"4[0-9]+__4[0-9]+"},
- }
-
- m := make(map[string]DefinedSet)
- for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
- asPathSet4, asPathSet5, asPathSet6, asPathSet7, asPathSet8, asPathSet9} {
- a, _ := NewAsPathSet(s)
- m[s.AsPathSetName] = a
- }
-
- createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition {
- matchSet := config.MatchAsPathSet{}
- matchSet.AsPathSet = name
- matchSet.MatchSetOptions = option
- p, _ := NewAsPathCondition(matchSet)
- if v, ok := m[name]; ok {
- p.set = v.(*AsPathSet)
- }
- return p
- }
-
- p1 := createAspathC("asset1", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p2 := createAspathC("asset2", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p3 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p4 := createAspathC("asset4", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p5 := createAspathC("asset5", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p6 := createAspathC("asset6", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p7 := createAspathC("asset7", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p8 := createAspathC("asset8", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p9 := createAspathC("asset9", config.MATCH_SET_OPTIONS_TYPE_ANY)
-
- // test
- assert.Equal(t, true, p1.Evaluate(path1, nil))
- assert.Equal(t, true, p2.Evaluate(path1, nil))
- assert.Equal(t, true, p3.Evaluate(path1, nil))
- assert.Equal(t, true, p4.Evaluate(path1, nil))
- assert.Equal(t, true, p5.Evaluate(path1, nil))
- assert.Equal(t, true, p6.Evaluate(path1, nil))
- assert.Equal(t, true, p7.Evaluate(path1, nil))
- assert.Equal(t, true, p8.Evaluate(path1, nil))
- assert.Equal(t, false, p9.Evaluate(path1, nil))
-}
-
-func TestAs4PathConditionWithOtherCondition(t *testing.T) {
-
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(1, []uint32{
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- createAs4Value("65004.1"),
- createAs4Value("65005.1"),
- }),
- bgp.NewAs4PathParam(2, []uint32{
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- createAs4Value("65004.1"),
- createAs4Value("65004.1"),
- createAs4Value("65005.1"),
- }),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- asPathSet := config.AsPathSet{
- AsPathSetName: "asset1",
- AsPathList: []string{fmt.Sprintf("%d$", createAs4Value("65005.1"))},
- }
-
- ps := createPrefixSet("ps1", "10.10.1.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
- ds.BgpDefinedSets.AsPathSets = []config.AsPathSet{asPathSet}
-
- s := createStatement("statement1", "ps1", "ns1", false)
- s.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = "asset1"
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- r.reload(pl)
- p, _ := NewPolicy(pl.PolicyDefinitions[0])
- addPolicy(r, p)
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_REJECT, pType)
- assert.Equal(t, newPath, path)
-
-}
-
-func TestAs4PathConditionEvaluateMixedWith2byteAS(t *testing.T) {
-
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam1 := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- createAs4Value("54000.1"),
- 100,
- 5000,
- createAs4Value("65004.1"),
- createAs4Value("65005.1"),
- 4000,
- }),
- }
-
- aspath := bgp.NewPathAttributeAsPath(aspathParam1)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate))
- path1 := ProcessMessage(updateMsg1, peer, time.Now())[0]
-
- // create match condition
- asPathSet1 := config.AsPathSet{
- AsPathSetName: "asset1",
- AsPathList: []string{fmt.Sprintf("^%d", createAs4Value("65001.1"))},
- }
-
- asPathSet2 := config.AsPathSet{
- AsPathSetName: "asset2",
- AsPathList: []string{"4000$"},
- }
-
- asPathSet3 := config.AsPathSet{
- AsPathSetName: "asset3",
- AsPathList: []string{fmt.Sprintf("%d", createAs4Value("65004.1")), "4000$"},
- }
-
- asPathSet4 := config.AsPathSet{
- AsPathSetName: "asset4",
- AsPathList: []string{fmt.Sprintf("%d_%d_%d", createAs4Value("54000.1"), 100, 5000)},
- }
-
- asPathSet5 := config.AsPathSet{
- AsPathSetName: "asset5",
- AsPathList: []string{".*_[0-9]+_100"},
- }
-
- asPathSet6 := config.AsPathSet{
- AsPathSetName: "asset6",
- AsPathList: []string{".*_3[0-9]+_[0]+"},
- }
-
- asPathSet7 := config.AsPathSet{
- AsPathSetName: "asset7",
- AsPathList: []string{".*_3[0-9]+_[1]+"},
- }
-
- m := make(map[string]DefinedSet)
- for _, s := range []config.AsPathSet{asPathSet1, asPathSet2, asPathSet3,
- asPathSet4, asPathSet5, asPathSet6, asPathSet7} {
- a, _ := NewAsPathSet(s)
- m[s.AsPathSetName] = a
- }
-
- createAspathC := func(name string, option config.MatchSetOptionsType) *AsPathCondition {
- matchSet := config.MatchAsPathSet{}
- matchSet.AsPathSet = name
- matchSet.MatchSetOptions = option
- p, _ := NewAsPathCondition(matchSet)
- if v, ok := m[name]; ok {
- p.set = v.(*AsPathSet)
- }
- return p
- }
-
- p1 := createAspathC("asset1", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p2 := createAspathC("asset2", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p3 := createAspathC("asset3", config.MATCH_SET_OPTIONS_TYPE_ALL)
- p4 := createAspathC("asset4", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p5 := createAspathC("asset5", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p6 := createAspathC("asset6", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p7 := createAspathC("asset7", config.MATCH_SET_OPTIONS_TYPE_ANY)
-
- // test
- assert.Equal(t, true, p1.Evaluate(path1, nil))
- assert.Equal(t, true, p2.Evaluate(path1, nil))
- assert.Equal(t, true, p3.Evaluate(path1, nil))
- assert.Equal(t, true, p4.Evaluate(path1, nil))
- assert.Equal(t, true, p5.Evaluate(path1, nil))
- assert.Equal(t, false, p6.Evaluate(path1, nil))
- assert.Equal(t, true, p7.Evaluate(path1, nil))
-
-}
-
-func TestCommunityConditionEvaluate(t *testing.T) {
-
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam1 := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 65005}),
- bgp.NewAsPathParam(1, []uint16{65001, 65010, 65004, 65005}),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam1)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- communities := bgp.NewPathAttributeCommunities([]uint32{
- stringToCommunityValue("65001:100"),
- stringToCommunityValue("65001:200"),
- stringToCommunityValue("65001:300"),
- stringToCommunityValue("65001:400"),
- 0x00000000,
- 0xFFFFFF01,
- 0xFFFFFF02,
- 0xFFFFFF03})
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate))
- path1 := ProcessMessage(updateMsg1, peer, time.Now())[0]
-
- communities2 := bgp.NewPathAttributeCommunities([]uint32{
- stringToCommunityValue("65001:100"),
- stringToCommunityValue("65001:200"),
- stringToCommunityValue("65001:300"),
- stringToCommunityValue("65001:400")})
-
- pathAttributes2 := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities2}
- updateMsg2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri)
- UpdatePathAttrs4ByteAs(updateMsg2.Body.(*bgp.BGPUpdate))
- path2 := ProcessMessage(updateMsg2, peer, time.Now())[0]
-
- // create match condition
- comSet1 := config.CommunitySet{
- CommunitySetName: "comset1",
- CommunityList: []string{"65001:10", "65001:50", "65001:100"},
- }
-
- comSet2 := config.CommunitySet{
- CommunitySetName: "comset2",
- CommunityList: []string{"65001:200"},
- }
-
- comSet3 := config.CommunitySet{
- CommunitySetName: "comset3",
- CommunityList: []string{"4259905936"},
- }
-
- comSet4 := config.CommunitySet{
- CommunitySetName: "comset4",
- CommunityList: []string{"^[0-9]*:300$"},
- }
-
- comSet5 := config.CommunitySet{
- CommunitySetName: "comset5",
- CommunityList: []string{"INTERNET"},
- }
-
- comSet6 := config.CommunitySet{
- CommunitySetName: "comset6",
- CommunityList: []string{"NO_EXPORT"},
- }
-
- comSet7 := config.CommunitySet{
- CommunitySetName: "comset7",
- CommunityList: []string{"NO_ADVERTISE"},
- }
-
- comSet8 := config.CommunitySet{
- CommunitySetName: "comset8",
- CommunityList: []string{"NO_EXPORT_SUBCONFED"},
- }
-
- comSet9 := config.CommunitySet{
- CommunitySetName: "comset9",
- CommunityList: []string{
- "65001:\\d+",
- "\\d+:\\d00",
- },
- }
-
- comSet10 := config.CommunitySet{
- CommunitySetName: "comset10",
- CommunityList: []string{
- "65001:1",
- "65001:2",
- "65001:3",
- },
- }
-
- m := make(map[string]DefinedSet)
-
- for _, c := range []config.CommunitySet{comSet1, comSet2, comSet3,
- comSet4, comSet5, comSet6, comSet7, comSet8, comSet9, comSet10} {
- s, _ := NewCommunitySet(c)
- m[c.CommunitySetName] = s
- }
-
- createCommunityC := func(name string, option config.MatchSetOptionsType) *CommunityCondition {
- matchSet := config.MatchCommunitySet{}
- matchSet.CommunitySet = name
- matchSet.MatchSetOptions = option
- c, _ := NewCommunityCondition(matchSet)
- if v, ok := m[name]; ok {
- c.set = v.(*CommunitySet)
- }
- return c
- }
-
- // ANY case
- p1 := createCommunityC("comset1", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p2 := createCommunityC("comset2", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p3 := createCommunityC("comset3", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p4 := createCommunityC("comset4", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p5 := createCommunityC("comset5", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p6 := createCommunityC("comset6", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p7 := createCommunityC("comset7", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p8 := createCommunityC("comset8", config.MATCH_SET_OPTIONS_TYPE_ANY)
-
- // ALL case
- p9 := createCommunityC("comset9", config.MATCH_SET_OPTIONS_TYPE_ALL)
-
- // INVERT case
- p10 := createCommunityC("comset10", config.MATCH_SET_OPTIONS_TYPE_INVERT)
-
- // test
- assert.Equal(t, true, p1.Evaluate(path1, nil))
- assert.Equal(t, true, p2.Evaluate(path1, nil))
- assert.Equal(t, true, p3.Evaluate(path1, nil))
- assert.Equal(t, true, p4.Evaluate(path1, nil))
- assert.Equal(t, true, p5.Evaluate(path1, nil))
- assert.Equal(t, true, p6.Evaluate(path1, nil))
- assert.Equal(t, true, p7.Evaluate(path1, nil))
- assert.Equal(t, true, p8.Evaluate(path1, nil))
- assert.Equal(t, true, p9.Evaluate(path2, nil))
- assert.Equal(t, true, p10.Evaluate(path1, nil))
-
-}
-
-func TestCommunityConditionEvaluateWithOtherCondition(t *testing.T) {
-
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(1, []uint16{65001, 65000, 65004, 65005}),
- bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 65004, 65005}),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- communities := bgp.NewPathAttributeCommunities([]uint32{
- stringToCommunityValue("65001:100"),
- stringToCommunityValue("65001:200"),
- stringToCommunityValue("65001:300"),
- stringToCommunityValue("65001:400"),
- 0x00000000,
- 0xFFFFFF01,
- 0xFFFFFF02,
- 0xFFFFFF03})
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- asPathSet := config.AsPathSet{
- AsPathSetName: "asset1",
- AsPathList: []string{"65005$"},
- }
-
- comSet1 := config.CommunitySet{
- CommunitySetName: "comset1",
- CommunityList: []string{"65001:100", "65001:200", "65001:300"},
- }
-
- comSet2 := config.CommunitySet{
- CommunitySetName: "comset2",
- CommunityList: []string{"65050:\\d+"},
- }
-
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
- ds.BgpDefinedSets.AsPathSets = []config.AsPathSet{asPathSet}
- ds.BgpDefinedSets.CommunitySets = []config.CommunitySet{comSet1, comSet2}
-
- s1 := createStatement("statement1", "ps1", "ns1", false)
- s1.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = "asset1"
- s1.Conditions.BgpConditions.MatchCommunitySet.CommunitySet = "comset1"
-
- s2 := createStatement("statement2", "ps1", "ns1", false)
- s2.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = "asset1"
- s2.Conditions.BgpConditions.MatchCommunitySet.CommunitySet = "comset2"
-
- pd1 := createPolicyDefinition("pd1", s1)
- pd2 := createPolicyDefinition("pd2", s2)
- pl := createRoutingPolicy(ds, pd1, pd2)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_REJECT, pType)
- assert.Equal(t, newPath, path)
-
- p = r.policyMap["pd2"]
- pType, newPath = p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_NONE, pType)
- assert.Equal(t, newPath, path)
-
-}
-
-func TestPolicyMatchAndAddCommunities(t *testing.T) {
-
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- community := "65000:100"
-
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetCommunity = createSetCommunity("ADD", community)
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
-
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(t, nil, newPath)
- assert.Equal(t, []uint32{stringToCommunityValue(community)}, newPath.GetCommunities())
-}
-
-func TestPolicyMatchAndReplaceCommunities(t *testing.T) {
-
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- communities := bgp.NewPathAttributeCommunities([]uint32{
- stringToCommunityValue("65001:200"),
- })
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- community := "65000:100"
-
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetCommunity = createSetCommunity("REPLACE", community)
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
-
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(t, nil, newPath)
- assert.Equal(t, []uint32{stringToCommunityValue(community)}, newPath.GetCommunities())
-}
-
-func TestPolicyMatchAndRemoveCommunities(t *testing.T) {
-
- // create path
- community1 := "65000:100"
- community2 := "65000:200"
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- communities := bgp.NewPathAttributeCommunities([]uint32{
- stringToCommunityValue(community1),
- stringToCommunityValue(community2),
- })
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetCommunity = createSetCommunity("REMOVE", community1)
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(t, nil, newPath)
- assert.Equal(t, []uint32{stringToCommunityValue(community2)}, newPath.GetCommunities())
-}
-
-func TestPolicyMatchAndRemoveCommunitiesRegexp(t *testing.T) {
-
- // create path
- community1 := "65000:100"
- community2 := "65000:200"
- community3 := "65100:100"
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- communities := bgp.NewPathAttributeCommunities([]uint32{
- stringToCommunityValue(community1),
- stringToCommunityValue(community2),
- stringToCommunityValue(community3),
- })
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetCommunity = createSetCommunity("REMOVE", ".*:100")
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(t, nil, newPath)
- assert.Equal(t, []uint32{stringToCommunityValue(community2)}, newPath.GetCommunities())
-}
-
-func TestPolicyMatchAndRemoveCommunitiesRegexp2(t *testing.T) {
-
- // create path
- community1 := "0:1"
- community2 := "10:1"
- community3 := "45686:2"
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- communities := bgp.NewPathAttributeCommunities([]uint32{
- stringToCommunityValue(community1),
- stringToCommunityValue(community2),
- stringToCommunityValue(community3),
- })
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetCommunity = createSetCommunity("REMOVE", "^(0|45686):[0-9]+")
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(t, nil, newPath)
- assert.Equal(t, []uint32{stringToCommunityValue(community2)}, newPath.GetCommunities())
-}
-
-func TestPolicyMatchAndClearCommunities(t *testing.T) {
-
- // create path
- community1 := "65000:100"
- community2 := "65000:200"
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- communities := bgp.NewPathAttributeCommunities([]uint32{
- stringToCommunityValue(community1),
- stringToCommunityValue(community2),
- })
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, communities}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- s := createStatement("statement1", "ps1", "ns1", true)
- // action NULL is obsolate
- s.Actions.BgpActions.SetCommunity.Options = "REPLACE"
- s.Actions.BgpActions.SetCommunity.SetCommunityMethod.CommunitiesList = nil
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
-
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(t, nil, newPath)
- //assert.Equal(t, []uint32{}, newPath.GetCommunities())
-}
-
-func TestExtCommunityConditionEvaluate(t *testing.T) {
-
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam1 := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 65005}),
- bgp.NewAsPathParam(1, []uint16{65001, 65010, 65004, 65005}),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam1)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- eComAsSpecific1 := &bgp.TwoOctetAsSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- AS: 65001,
- LocalAdmin: 200,
- IsTransitive: true,
- }
- eComIpPrefix1 := &bgp.IPv4AddressSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- IPv4: net.ParseIP("10.0.0.1"),
- LocalAdmin: 300,
- IsTransitive: true,
- }
- eComAs4Specific1 := &bgp.FourOctetAsSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- AS: 65030000,
- LocalAdmin: 200,
- IsTransitive: true,
- }
- eComAsSpecific2 := &bgp.TwoOctetAsSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- AS: 65002,
- LocalAdmin: 200,
- IsTransitive: false,
- }
- eComIpPrefix2 := &bgp.IPv4AddressSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- IPv4: net.ParseIP("10.0.0.2"),
- LocalAdmin: 300,
- IsTransitive: false,
- }
- eComAs4Specific2 := &bgp.FourOctetAsSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- AS: 65030001,
- LocalAdmin: 200,
- IsTransitive: false,
- }
- eComAsSpecific3 := &bgp.TwoOctetAsSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_ORIGIN),
- AS: 65010,
- LocalAdmin: 300,
- IsTransitive: true,
- }
- eComIpPrefix3 := &bgp.IPv4AddressSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_ORIGIN),
- IPv4: net.ParseIP("10.0.10.10"),
- LocalAdmin: 400,
- IsTransitive: true,
- }
- eComAs4Specific3 := &bgp.FourOctetAsSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- AS: 65030002,
- LocalAdmin: 500,
- IsTransitive: true,
- }
- ec := []bgp.ExtendedCommunityInterface{eComAsSpecific1, eComIpPrefix1, eComAs4Specific1, eComAsSpecific2,
- eComIpPrefix2, eComAs4Specific2, eComAsSpecific3, eComIpPrefix3, eComAs4Specific3}
- extCommunities := bgp.NewPathAttributeExtendedCommunities(ec)
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, extCommunities}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg1.Body.(*bgp.BGPUpdate))
- path1 := ProcessMessage(updateMsg1, peer, time.Now())[0]
-
- convUintStr := func(as uint32) string {
- upper := strconv.FormatUint(uint64(as&0xFFFF0000>>16), 10)
- lower := strconv.FormatUint(uint64(as&0x0000FFFF), 10)
- str := fmt.Sprintf("%s.%s", upper, lower)
- return str
- }
-
- // create match condition
- ecomSet1 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet1",
- ExtCommunityList: []string{"RT:65001:200"},
- }
- ecomSet2 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet2",
- ExtCommunityList: []string{"RT:10.0.0.1:300"},
- }
- ecomSet3 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet3",
- ExtCommunityList: []string{fmt.Sprintf("RT:%s:200", convUintStr(65030000))},
- }
- ecomSet4 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet4",
- ExtCommunityList: []string{"RT:65002:200"},
- }
- ecomSet5 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet5",
- ExtCommunityList: []string{"RT:10.0.0.2:300"},
- }
- ecomSet6 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet6",
- ExtCommunityList: []string{fmt.Sprintf("RT:%s:200", convUintStr(65030001))},
- }
- ecomSet7 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet7",
- ExtCommunityList: []string{"SoO:65010:300"},
- }
- ecomSet8 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet8",
- ExtCommunityList: []string{"SoO:10.0.10.10:[0-9]+"},
- }
- ecomSet9 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet9",
- ExtCommunityList: []string{"RT:[0-9]+:[0-9]+"},
- }
- ecomSet10 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet10",
- ExtCommunityList: []string{"RT:.+:\\d00", "SoO:.+:\\d00"},
- }
-
- ecomSet11 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet11",
- ExtCommunityList: []string{"RT:65001:2", "SoO:11.0.10.10:[0-9]+"},
- }
-
- m := make(map[string]DefinedSet)
- for _, c := range []config.ExtCommunitySet{ecomSet1, ecomSet2, ecomSet3, ecomSet4, ecomSet5, ecomSet6, ecomSet7,
- ecomSet8, ecomSet9, ecomSet10, ecomSet11} {
- s, _ := NewExtCommunitySet(c)
- m[s.Name()] = s
- }
-
- createExtCommunityC := func(name string, option config.MatchSetOptionsType) *ExtCommunityCondition {
- matchSet := config.MatchExtCommunitySet{}
- matchSet.ExtCommunitySet = name
- matchSet.MatchSetOptions = option
- c, _ := NewExtCommunityCondition(matchSet)
- if v, ok := m[name]; ok {
- c.set = v.(*ExtCommunitySet)
- }
-
- return c
- }
-
- p1 := createExtCommunityC("ecomSet1", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p2 := createExtCommunityC("ecomSet2", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p3 := createExtCommunityC("ecomSet3", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p4 := createExtCommunityC("ecomSet4", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p5 := createExtCommunityC("ecomSet5", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p6 := createExtCommunityC("ecomSet6", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p7 := createExtCommunityC("ecomSet7", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p8 := createExtCommunityC("ecomSet8", config.MATCH_SET_OPTIONS_TYPE_ANY)
- p9 := createExtCommunityC("ecomSet9", config.MATCH_SET_OPTIONS_TYPE_ANY)
-
- // ALL case
- p10 := createExtCommunityC("ecomSet10", config.MATCH_SET_OPTIONS_TYPE_ALL)
-
- // INVERT case
- p11 := createExtCommunityC("ecomSet11", config.MATCH_SET_OPTIONS_TYPE_INVERT)
-
- // test
- assert.Equal(t, true, p1.Evaluate(path1, nil))
- assert.Equal(t, true, p2.Evaluate(path1, nil))
- assert.Equal(t, true, p3.Evaluate(path1, nil))
- assert.Equal(t, false, p4.Evaluate(path1, nil))
- assert.Equal(t, false, p5.Evaluate(path1, nil))
- assert.Equal(t, false, p6.Evaluate(path1, nil))
- assert.Equal(t, true, p7.Evaluate(path1, nil))
- assert.Equal(t, true, p8.Evaluate(path1, nil))
- assert.Equal(t, true, p9.Evaluate(path1, nil))
- assert.Equal(t, true, p10.Evaluate(path1, nil))
- assert.Equal(t, true, p11.Evaluate(path1, nil))
-
-}
-
-func TestExtCommunityConditionEvaluateWithOtherCondition(t *testing.T) {
-
- // setup
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.2.1.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAsPathParam(1, []uint16{65001, 65000, 65004, 65005}),
- bgp.NewAsPathParam(2, []uint16{65001, 65000, 65004, 65004, 65005}),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.2.1.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
- eComAsSpecific1 := &bgp.TwoOctetAsSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- AS: 65001,
- LocalAdmin: 200,
- IsTransitive: true,
- }
- eComIpPrefix1 := &bgp.IPv4AddressSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- IPv4: net.ParseIP("10.0.0.1"),
- LocalAdmin: 300,
- IsTransitive: true,
- }
- eComAs4Specific1 := &bgp.FourOctetAsSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- AS: 65030000,
- LocalAdmin: 200,
- IsTransitive: true,
- }
- eComAsSpecific2 := &bgp.TwoOctetAsSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- AS: 65002,
- LocalAdmin: 200,
- IsTransitive: false,
- }
- eComIpPrefix2 := &bgp.IPv4AddressSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- IPv4: net.ParseIP("10.0.0.2"),
- LocalAdmin: 300,
- IsTransitive: false,
- }
- eComAs4Specific2 := &bgp.FourOctetAsSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- AS: 65030001,
- LocalAdmin: 200,
- IsTransitive: false,
- }
- eComAsSpecific3 := &bgp.TwoOctetAsSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_ORIGIN),
- AS: 65010,
- LocalAdmin: 300,
- IsTransitive: true,
- }
- eComIpPrefix3 := &bgp.IPv4AddressSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_ORIGIN),
- IPv4: net.ParseIP("10.0.10.10"),
- LocalAdmin: 400,
- IsTransitive: true,
- }
- eComAs4Specific3 := &bgp.FourOctetAsSpecificExtended{
- SubType: bgp.ExtendedCommunityAttrSubType(bgp.EC_SUBTYPE_ROUTE_TARGET),
- AS: 65030002,
- LocalAdmin: 500,
- IsTransitive: true,
- }
- ec := []bgp.ExtendedCommunityInterface{eComAsSpecific1, eComIpPrefix1, eComAs4Specific1, eComAsSpecific2,
- eComIpPrefix2, eComAs4Specific2, eComAsSpecific3, eComIpPrefix3, eComAs4Specific3}
- extCommunities := bgp.NewPathAttributeExtendedCommunities(ec)
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med, extCommunities}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate))
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- asPathSet := config.AsPathSet{
- AsPathSetName: "asset1",
- AsPathList: []string{"65005$"},
- }
-
- ecomSet1 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet1",
- ExtCommunityList: []string{"RT:65001:201"},
- }
- ecomSet2 := config.ExtCommunitySet{
- ExtCommunitySetName: "ecomSet2",
- ExtCommunityList: []string{"RT:[0-9]+:[0-9]+"},
- }
-
- ps := createPrefixSet("ps1", "10.10.1.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.2.1.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
- ds.BgpDefinedSets.AsPathSets = []config.AsPathSet{asPathSet}
- ds.BgpDefinedSets.ExtCommunitySets = []config.ExtCommunitySet{ecomSet1, ecomSet2}
-
- s1 := createStatement("statement1", "ps1", "ns1", false)
- s1.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = "asset1"
- s1.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet = "ecomSet1"
-
- s2 := createStatement("statement2", "ps1", "ns1", false)
- s2.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = "asset1"
- s2.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet = "ecomSet2"
-
- pd1 := createPolicyDefinition("pd1", s1)
- pd2 := createPolicyDefinition("pd2", s2)
- pl := createRoutingPolicy(ds, pd1, pd2)
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_NONE, pType)
- assert.Equal(t, newPath, path)
-
- p = r.policyMap["pd2"]
- pType, newPath = p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_REJECT, pType)
- assert.Equal(t, newPath, path)
-
-}
-
-func TestPolicyMatchAndReplaceMed(t *testing.T) {
-
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- m := "200"
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetMed = config.BgpSetMedType(m)
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
-
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
-
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(t, nil, newPath)
- v, err := newPath.GetMed()
- assert.Nil(t, err)
- newMed := fmt.Sprintf("%d", v)
- assert.Equal(t, m, newMed)
-}
-
-func TestPolicyMatchAndAddingMed(t *testing.T) {
-
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- m := "+200"
- ma := "300"
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetMed = config.BgpSetMedType(m)
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(t, nil, newPath)
-
- v, err := newPath.GetMed()
- assert.Nil(t, err)
- newMed := fmt.Sprintf("%d", v)
- assert.Equal(t, ma, newMed)
-}
-
-func TestPolicyMatchAndAddingMedOverFlow(t *testing.T) {
-
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(1)
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- m := fmt.Sprintf("+%d", uint32(math.MaxUint32))
- ma := "1"
-
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetMed = config.BgpSetMedType(m)
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
-
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(t, nil, newPath)
-
- v, err := newPath.GetMed()
- assert.Nil(t, err)
- newMed := fmt.Sprintf("%d", v)
- assert.Equal(t, ma, newMed)
-}
-
-func TestPolicyMatchAndSubtractMed(t *testing.T) {
-
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- m := "-50"
- ma := "50"
-
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetMed = config.BgpSetMedType(m)
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
-
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(t, nil, newPath)
-
- v, err := newPath.GetMed()
- assert.Nil(t, err)
- newMed := fmt.Sprintf("%d", v)
- assert.Equal(t, ma, newMed)
-}
-
-func TestPolicyMatchAndSubtractMedUnderFlow(t *testing.T) {
-
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- m := "-101"
- ma := "100"
-
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetMed = config.BgpSetMedType(m)
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
-
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(t, nil, newPath)
-
- v, err := newPath.GetMed()
- assert.Nil(t, err)
- newMed := fmt.Sprintf("%d", v)
- assert.Equal(t, ma, newMed)
-}
-
-func TestPolicyMatchWhenPathHaveNotMed(t *testing.T) {
-
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- m := "-50"
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetMed = config.BgpSetMedType(m)
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
- //test
- r := NewRoutingPolicy()
- err := r.reload(pl)
- assert.Nil(t, err)
- p := r.policyMap["pd1"]
-
- pType, newPath := p.Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(t, nil, newPath)
-
- _, err = newPath.GetMed()
- assert.NotNil(t, err)
-}
-
-func TestPolicyAsPathPrepend(t *testing.T) {
-
- assert := assert.New(t)
-
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001, 65000})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
-
- body := updateMsg.Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(body)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetAsPathPrepend.As = "65002"
- s.Actions.BgpActions.SetAsPathPrepend.RepeatN = 10
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
- //test
- r := NewRoutingPolicy()
- r.reload(pl)
- p := r.policyMap["pd1"]
-
- pType, newPath := p.Apply(path, nil)
- assert.Equal(ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(nil, newPath)
- assert.Equal([]uint32{65002, 65002, 65002, 65002, 65002, 65002, 65002, 65002, 65002, 65002, 65001, 65000}, newPath.GetAsSeqList())
-}
-
-func TestPolicyAsPathPrependLastAs(t *testing.T) {
-
- assert := assert.New(t)
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65002, 65001, 65000})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
-
- body := updateMsg.Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(body)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetAsPathPrepend.As = "last-as"
- s.Actions.BgpActions.SetAsPathPrepend.RepeatN = 5
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
- //test
- r := NewRoutingPolicy()
- r.reload(pl)
- p := r.policyMap["pd1"]
-
- pType, newPath := p.Apply(path, nil)
- assert.Equal(ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(nil, newPath)
- assert.Equal([]uint32{65002, 65002, 65002, 65002, 65002, 65002, 65001, 65000}, newPath.GetAsSeqList())
-}
-
-func TestPolicyAs4PathPrepend(t *testing.T) {
-
- assert := assert.New(t)
-
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- }),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
-
- body := updateMsg.Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(body)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetAsPathPrepend.As = fmt.Sprintf("%d", createAs4Value("65002.1"))
- s.Actions.BgpActions.SetAsPathPrepend.RepeatN = 10
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
- //test
- r := NewRoutingPolicy()
- r.reload(pl)
- p, err := NewPolicy(pl.PolicyDefinitions[0])
- assert.Nil(err)
- addPolicy(r, p)
-
- pType, newPath := p.Apply(path, nil)
- assert.Equal(ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(nil, newPath)
- asn := createAs4Value("65002.1")
- assert.Equal([]uint32{
- asn, asn, asn, asn, asn, asn, asn, asn, asn, asn,
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- }, newPath.GetAsSeqList())
-}
-
-func TestPolicyAs4PathPrependLastAs(t *testing.T) {
-
- assert := assert.New(t)
- // create path
- peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")}
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{
- createAs4Value("65002.1"),
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- }),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
-
- pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")}
- updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
-
- body := updateMsg.Body.(*bgp.BGPUpdate)
- UpdatePathAttrs4ByteAs(body)
- path := ProcessMessage(updateMsg, peer, time.Now())[0]
-
- // create policy
- ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24")
- ns := createNeighborSet("ns1", "10.0.0.1")
-
- ds := config.DefinedSets{}
- ds.PrefixSets = []config.PrefixSet{ps}
- ds.NeighborSets = []config.NeighborSet{ns}
-
- s := createStatement("statement1", "ps1", "ns1", true)
- s.Actions.BgpActions.SetAsPathPrepend.As = "last-as"
- s.Actions.BgpActions.SetAsPathPrepend.RepeatN = 5
-
- pd := createPolicyDefinition("pd1", s)
- pl := createRoutingPolicy(ds, pd)
- //test
- r := NewRoutingPolicy()
- r.reload(pl)
- p, _ := NewPolicy(pl.PolicyDefinitions[0])
- addPolicy(r, p)
-
- pType, newPath := p.Apply(path, nil)
- assert.Equal(ROUTE_TYPE_ACCEPT, pType)
- assert.NotEqual(nil, newPath)
- asn := createAs4Value("65002.1")
- assert.Equal([]uint32{
- asn, asn, asn, asn, asn,
- createAs4Value("65002.1"),
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- }, newPath.GetAsSeqList())
-}
-
-func TestParseCommunityRegexp(t *testing.T) {
- exp, err := ParseCommunityRegexp("65000:1")
- assert.Equal(t, nil, err)
- assert.Equal(t, true, exp.MatchString("65000:1"))
- assert.Equal(t, false, exp.MatchString("65000:100"))
-}
-
-func TestLocalPrefAction(t *testing.T) {
- action, err := NewLocalPrefAction(10)
- assert.Nil(t, err)
-
- nlri := bgp.NewIPAddrPrefix(24, "10.0.0.0")
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{
- bgp.NewAs4PathParam(2, []uint32{
- createAs4Value("65002.1"),
- createAs4Value("65001.1"),
- createAs4Value("65000.1"),
- }),
- }
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
-
- attrs := []bgp.PathAttributeInterface{origin, aspath, nexthop, med}
-
- path := NewPath(nil, nlri, false, attrs, time.Now(), false)
- p := action.Apply(path, nil)
- assert.NotNil(t, p)
-
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF)
- assert.NotNil(t, attr)
- lp := attr.(*bgp.PathAttributeLocalPref)
- assert.Equal(t, int(lp.Value), int(10))
-}
-
-func createStatement(name, psname, nsname string, accept bool) config.Statement {
- c := config.Conditions{
- MatchPrefixSet: config.MatchPrefixSet{
- PrefixSet: psname,
- },
- MatchNeighborSet: config.MatchNeighborSet{
- NeighborSet: nsname,
- },
- }
- rd := config.ROUTE_DISPOSITION_REJECT_ROUTE
- if accept {
- rd = config.ROUTE_DISPOSITION_ACCEPT_ROUTE
- }
- a := config.Actions{
- RouteDisposition: rd,
- }
- s := config.Statement{
- Name: name,
- Conditions: c,
- Actions: a,
- }
- return s
-}
-
-func createSetCommunity(operation string, community ...string) config.SetCommunity {
-
- s := config.SetCommunity{
- SetCommunityMethod: config.SetCommunityMethod{
- CommunitiesList: community,
- },
- Options: operation,
- }
- return s
-}
-
-func stringToCommunityValue(comStr string) uint32 {
- elem := strings.Split(comStr, ":")
- asn, _ := strconv.ParseUint(elem[0], 10, 16)
- val, _ := strconv.ParseUint(elem[1], 10, 16)
- return uint32(asn<<16 | val)
-}
-
-func createPolicyDefinition(defName string, stmt ...config.Statement) config.PolicyDefinition {
- pd := config.PolicyDefinition{
- Name: defName,
- Statements: []config.Statement(stmt),
- }
- return pd
-}
-
-func createRoutingPolicy(ds config.DefinedSets, pd ...config.PolicyDefinition) config.RoutingPolicy {
- pl := config.RoutingPolicy{
- DefinedSets: ds,
- PolicyDefinitions: []config.PolicyDefinition(pd),
- }
- return pl
-}
-
-func createPrefixSet(name string, prefix string, maskLength string) config.PrefixSet {
- ps := config.PrefixSet{
- PrefixSetName: name,
- PrefixList: []config.Prefix{
- config.Prefix{
- IpPrefix: prefix,
- MasklengthRange: maskLength,
- }},
- }
- return ps
-}
-
-func createNeighborSet(name string, addr string) config.NeighborSet {
- ns := config.NeighborSet{
- NeighborSetName: name,
- NeighborInfoList: []string{addr},
- }
- return ns
-}
-
-func createAs4Value(s string) uint32 {
- v := strings.Split(s, ".")
- upper, _ := strconv.ParseUint(v[0], 10, 16)
- lower, _ := strconv.ParseUint(v[1], 10, 16)
- return uint32(upper<<16 | lower)
-}
-
-func TestPrefixSetOperation(t *testing.T) {
- // tryp to create prefixset with multiple families
- p1 := config.Prefix{
- IpPrefix: "0.0.0.0/0",
- MasklengthRange: "0..7",
- }
- p2 := config.Prefix{
- IpPrefix: "0::/25",
- MasklengthRange: "25..128",
- }
- _, err := NewPrefixSet(config.PrefixSet{
- PrefixSetName: "ps1",
- PrefixList: []config.Prefix{p1, p2},
- })
- assert.NotNil(t, err)
- m1, _ := NewPrefixSet(config.PrefixSet{
- PrefixSetName: "ps1",
- PrefixList: []config.Prefix{p1},
- })
- m2, err := NewPrefixSet(config.PrefixSet{PrefixSetName: "ps2"})
- assert.Nil(t, err)
- err = m1.Append(m2)
- assert.Nil(t, err)
- err = m2.Append(m1)
- assert.Nil(t, err)
- assert.Equal(t, bgp.RF_IPv4_UC, m2.family)
- p3, _ := NewPrefix(config.Prefix{IpPrefix: "10.10.0.0/24", MasklengthRange: ""})
- p4, _ := NewPrefix(config.Prefix{IpPrefix: "0::/25", MasklengthRange: ""})
- _, err = NewPrefixSetFromApiStruct("ps3", []*Prefix{p3, p4})
- assert.NotNil(t, err)
-}
-
-func TestPrefixSetMatch(t *testing.T) {
- p1 := config.Prefix{
- IpPrefix: "0.0.0.0/0",
- MasklengthRange: "0..7",
- }
- p2 := config.Prefix{
- IpPrefix: "0.0.0.0/0",
- MasklengthRange: "25..32",
- }
- ps, err := NewPrefixSet(config.PrefixSet{
- PrefixSetName: "ps1",
- PrefixList: []config.Prefix{p1, p2},
- })
- assert.Nil(t, err)
- m := &PrefixCondition{
- set: ps,
- }
-
- path := NewPath(nil, bgp.NewIPAddrPrefix(6, "0.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false)
- assert.True(t, m.Evaluate(path, nil))
-
- path = NewPath(nil, bgp.NewIPAddrPrefix(10, "0.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false)
- assert.False(t, m.Evaluate(path, nil))
-
- path = NewPath(nil, bgp.NewIPAddrPrefix(25, "0.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false)
- assert.True(t, m.Evaluate(path, nil))
-
- path = NewPath(nil, bgp.NewIPAddrPrefix(30, "0.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false)
- assert.True(t, m.Evaluate(path, nil))
-
- p3 := config.Prefix{
- IpPrefix: "0.0.0.0/0",
- MasklengthRange: "9..10",
- }
- ps2, err := NewPrefixSet(config.PrefixSet{
- PrefixSetName: "ps2",
- PrefixList: []config.Prefix{p3},
- })
- assert.Nil(t, err)
- err = ps.Append(ps2)
- assert.Nil(t, err)
-
- path = NewPath(nil, bgp.NewIPAddrPrefix(10, "0.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false)
- assert.True(t, m.Evaluate(path, nil))
-
- ps3, err := NewPrefixSet(config.PrefixSet{
- PrefixSetName: "ps3",
- PrefixList: []config.Prefix{p1},
- })
- assert.Nil(t, err)
- err = ps.Remove(ps3)
- assert.Nil(t, err)
-
- path = NewPath(nil, bgp.NewIPAddrPrefix(6, "0.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false)
- assert.False(t, m.Evaluate(path, nil))
-}
-
-func TestPrefixSetMatchV4withV6Prefix(t *testing.T) {
- p1 := config.Prefix{
- IpPrefix: "c000::/3",
- MasklengthRange: "3..128",
- }
- ps, err := NewPrefixSet(config.PrefixSet{
- PrefixSetName: "ps1",
- PrefixList: []config.Prefix{p1},
- })
- assert.Nil(t, err)
- m := &PrefixCondition{
- set: ps,
- }
-
- path := NewPath(nil, bgp.NewIPAddrPrefix(6, "192.0.0.0"), false, []bgp.PathAttributeInterface{}, time.Now(), false)
- assert.False(t, m.Evaluate(path, nil))
-}
-
-func TestLargeCommunityMatchAction(t *testing.T) {
- coms := []*bgp.LargeCommunity{
- &bgp.LargeCommunity{ASN: 100, LocalData1: 100, LocalData2: 100},
- &bgp.LargeCommunity{ASN: 100, LocalData1: 200, LocalData2: 200},
- }
- p := NewPath(nil, nil, false, []bgp.PathAttributeInterface{bgp.NewPathAttributeLargeCommunities(coms)}, time.Time{}, false)
-
- c := config.LargeCommunitySet{
- LargeCommunitySetName: "l0",
- LargeCommunityList: []string{
- "100:100:100",
- "100:300:100",
- },
- }
-
- set, err := NewLargeCommunitySet(c)
- assert.Equal(t, err, nil)
-
- m, err := NewLargeCommunityCondition(config.MatchLargeCommunitySet{
- LargeCommunitySet: "l0",
- })
- assert.Equal(t, err, nil)
- m.set = set
-
- assert.Equal(t, m.Evaluate(p, nil), true)
-
- a, err := NewLargeCommunityAction(config.SetLargeCommunity{
- SetLargeCommunityMethod: config.SetLargeCommunityMethod{
- CommunitiesList: []string{"100:100:100"},
- },
- Options: config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE,
- })
- assert.Equal(t, err, nil)
- p = a.Apply(p, nil)
-
- assert.Equal(t, m.Evaluate(p, nil), false)
-
- a, err = NewLargeCommunityAction(config.SetLargeCommunity{
- SetLargeCommunityMethod: config.SetLargeCommunityMethod{
- CommunitiesList: []string{
- "100:300:100",
- "200:100:100",
- },
- },
- Options: config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD,
- })
- assert.Equal(t, err, nil)
- p = a.Apply(p, nil)
-
- assert.Equal(t, m.Evaluate(p, nil), true)
-
- a, err = NewLargeCommunityAction(config.SetLargeCommunity{
- SetLargeCommunityMethod: config.SetLargeCommunityMethod{
- CommunitiesList: []string{"^100:"},
- },
- Options: config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE,
- })
- assert.Equal(t, err, nil)
- p = a.Apply(p, nil)
-
- assert.Equal(t, m.Evaluate(p, nil), false)
-
- c = config.LargeCommunitySet{
- LargeCommunitySetName: "l1",
- LargeCommunityList: []string{
- "200:",
- },
- }
-
- set, err = NewLargeCommunitySet(c)
- assert.Equal(t, err, nil)
-
- m, err = NewLargeCommunityCondition(config.MatchLargeCommunitySet{
- LargeCommunitySet: "l1",
- })
- assert.Equal(t, err, nil)
- m.set = set
-
- assert.Equal(t, m.Evaluate(p, nil), true)
-}
-
-func TestAfiSafiInMatchPath(t *testing.T) {
- condition, err := NewAfiSafiInCondition([]config.AfiSafiType{config.AFI_SAFI_TYPE_L3VPN_IPV4_UNICAST, config.AFI_SAFI_TYPE_L3VPN_IPV6_UNICAST})
- require.NoError(t, err)
-
- rtExtCom, err := bgp.ParseExtendedCommunity(bgp.EC_SUBTYPE_ROUTE_TARGET, "100:100")
- assert.NoError(t, err)
-
- prefixVPNv4 := bgp.NewLabeledVPNIPAddrPrefix(0, "1.1.1.0/24", *bgp.NewMPLSLabelStack(), bgp.NewRouteDistinguisherTwoOctetAS(100, 100))
- prefixVPNv6 := bgp.NewLabeledVPNIPv6AddrPrefix(0, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", *bgp.NewMPLSLabelStack(), bgp.NewRouteDistinguisherTwoOctetAS(200, 200))
- prefixRTC := bgp.NewRouteTargetMembershipNLRI(100, nil)
- prefixv4 := bgp.NewIPAddrPrefix(0, "1.1.1.0/24")
- prefixv6 := bgp.NewIPv6AddrPrefix(0, "2001:0db8:85a3:0000:0000:8a2e:0370:7334")
-
- pathVPNv4 := NewPath(nil, prefixVPNv4, false, []bgp.PathAttributeInterface{bgp.NewPathAttributeExtendedCommunities([]bgp.ExtendedCommunityInterface{rtExtCom})}, time.Time{}, false)
- pathVPNv6 := NewPath(nil, prefixVPNv6, false, []bgp.PathAttributeInterface{bgp.NewPathAttributeExtendedCommunities([]bgp.ExtendedCommunityInterface{rtExtCom})}, time.Time{}, false)
- pathv4 := NewPath(nil, prefixv4, false, []bgp.PathAttributeInterface{}, time.Time{}, false)
- pathv6 := NewPath(nil, prefixv6, false, []bgp.PathAttributeInterface{}, time.Time{}, false)
- pathRTC := NewPath(nil, prefixRTC, false, []bgp.PathAttributeInterface{}, time.Time{}, false)
-
- type Entry struct {
- path *Path
- shouldMatch bool
- }
-
- for _, entry := range []Entry{
- {pathVPNv4, true},
- {pathVPNv6, true},
- {pathv4, false},
- {pathv6, false},
- {pathRTC, false},
- } {
- assert.Equal(t, condition.Evaluate(entry.path, nil), entry.shouldMatch)
- }
-}
-
-func TestMultipleStatementPolicy(t *testing.T) {
- r := NewRoutingPolicy()
- rp := config.RoutingPolicy{
- PolicyDefinitions: []config.PolicyDefinition{config.PolicyDefinition{
- Name: "p1",
- Statements: []config.Statement{
- config.Statement{
- Actions: config.Actions{
- BgpActions: config.BgpActions{
- SetMed: "+100",
- },
- },
- },
- config.Statement{
- Actions: config.Actions{
- BgpActions: config.BgpActions{
- SetLocalPref: 100,
- },
- },
- },
- },
- },
- },
- }
- err := r.reload(rp)
- assert.Nil(t, err)
-
- nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0")
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("10.0.0.1")
- pattrs := []bgp.PathAttributeInterface{origin, aspath, nexthop}
-
- path := NewPath(nil, nlri, false, pattrs, time.Now(), false)
-
- pType, newPath := r.policyMap["p1"].Apply(path, nil)
- assert.Equal(t, ROUTE_TYPE_NONE, pType)
- med, _ := newPath.GetMed()
- assert.Equal(t, med, uint32(100))
- localPref, _ := newPath.GetLocalPref()
- assert.Equal(t, localPref, uint32(100))
-}
diff --git a/table/roa.go b/table/roa.go
deleted file mode 100644
index fe08fe54..00000000
--- a/table/roa.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (C) 2016 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"
- "net"
-)
-
-type IPPrefix struct {
- Prefix net.IP
- Length uint8
-}
-
-func (p *IPPrefix) String() string {
- return fmt.Sprintf("%s/%d", p.Prefix, p.Length)
-}
-
-type ROA struct {
- Family int
- Prefix *IPPrefix
- MaxLen uint8
- AS uint32
- Src string
-}
-
-func NewROA(family int, prefixByte []byte, prefixLen uint8, maxLen uint8, as uint32, src string) *ROA {
- p := make([]byte, len(prefixByte))
- copy(p, prefixByte)
- return &ROA{
- Family: family,
- Prefix: &IPPrefix{
- Prefix: p,
- Length: prefixLen,
- },
- MaxLen: maxLen,
- AS: as,
- Src: src,
- }
-}
-
-func (r *ROA) Equal(roa *ROA) bool {
- if r.MaxLen == roa.MaxLen && r.Src == roa.Src && r.AS == roa.AS {
- return true
- }
- return false
-}
diff --git a/table/table.go b/table/table.go
deleted file mode 100644
index 82259b0f..00000000
--- a/table/table.go
+++ /dev/null
@@ -1,451 +0,0 @@
-// Copyright (C) 2014 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"
- "net"
- "strings"
- "unsafe"
-
- "github.com/armon/go-radix"
- "github.com/osrg/gobgp/packet/bgp"
- log "github.com/sirupsen/logrus"
-)
-
-type LookupOption uint8
-
-const (
- LOOKUP_EXACT LookupOption = iota
- LOOKUP_LONGER
- LOOKUP_SHORTER
-)
-
-type LookupPrefix struct {
- Prefix string
- LookupOption
-}
-
-type TableSelectOption struct {
- ID string
- AS uint32
- LookupPrefixes []*LookupPrefix
- VRF *Vrf
- adj bool
- Best bool
- MultiPath bool
-}
-
-type Table struct {
- routeFamily bgp.RouteFamily
- destinations map[string]*Destination
-}
-
-func NewTable(rf bgp.RouteFamily, dsts ...*Destination) *Table {
- t := &Table{
- routeFamily: rf,
- destinations: make(map[string]*Destination),
- }
- for _, dst := range dsts {
- t.setDestination(dst)
- }
- return t
-}
-
-func (t *Table) GetRoutefamily() bgp.RouteFamily {
- return t.routeFamily
-}
-
-func (t *Table) deletePathsByVrf(vrf *Vrf) []*Path {
- pathList := make([]*Path, 0)
- for _, dest := range t.destinations {
- for _, p := range dest.knownPathList {
- var rd bgp.RouteDistinguisherInterface
- nlri := p.GetNlri()
- switch nlri.(type) {
- case *bgp.LabeledVPNIPAddrPrefix:
- rd = nlri.(*bgp.LabeledVPNIPAddrPrefix).RD
- case *bgp.LabeledVPNIPv6AddrPrefix:
- rd = nlri.(*bgp.LabeledVPNIPv6AddrPrefix).RD
- case *bgp.EVPNNLRI:
- rd = nlri.(*bgp.EVPNNLRI).RD()
- default:
- return pathList
- }
- if p.IsLocal() && vrf.Rd.String() == rd.String() {
- pathList = append(pathList, p.Clone(true))
- break
- }
- }
- }
- return pathList
-}
-
-func (t *Table) deleteRTCPathsByVrf(vrf *Vrf, vrfs map[string]*Vrf) []*Path {
- pathList := make([]*Path, 0)
- if t.routeFamily != bgp.RF_RTC_UC {
- return pathList
- }
- for _, target := range vrf.ImportRt {
- lhs := target.String()
- for _, dest := range t.destinations {
- nlri := dest.GetNlri().(*bgp.RouteTargetMembershipNLRI)
- rhs := nlri.RouteTarget.String()
- if lhs == rhs && isLastTargetUser(vrfs, target) {
- for _, p := range dest.knownPathList {
- if p.IsLocal() {
- pathList = append(pathList, p.Clone(true))
- break
- }
- }
- }
- }
- }
- return pathList
-}
-
-func (t *Table) deleteDestByNlri(nlri bgp.AddrPrefixInterface) *Destination {
- if dst := t.GetDestination(nlri); dst != nil {
- t.deleteDest(dst)
- return dst
- }
- return nil
-}
-
-func (t *Table) deleteDest(dest *Destination) {
- destinations := t.GetDestinations()
- delete(destinations, t.tableKey(dest.GetNlri()))
- if len(destinations) == 0 {
- t.destinations = make(map[string]*Destination)
- }
-}
-
-func (t *Table) validatePath(path *Path) {
- if path == nil {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Key": t.routeFamily,
- }).Error("path is nil")
- }
- if path.GetRouteFamily() != t.routeFamily {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Key": t.routeFamily,
- "Prefix": path.GetNlri().String(),
- "ReceivedRf": path.GetRouteFamily().String(),
- }).Error("Invalid path. RouteFamily mismatch")
- }
- if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH); attr != nil {
- pathParam := attr.(*bgp.PathAttributeAsPath).Value
- for _, as := range pathParam {
- _, y := as.(*bgp.As4PathParam)
- if !y {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Key": t.routeFamily,
- "As": as,
- }).Fatal("AsPathParam must be converted to As4PathParam")
- }
- }
- }
- if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS4_PATH); attr != nil {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Key": t.routeFamily,
- }).Fatal("AS4_PATH must be converted to AS_PATH")
- }
- if path.GetNlri() == nil {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Key": t.routeFamily,
- }).Fatal("path's nlri is nil")
- }
-}
-
-func (t *Table) getOrCreateDest(nlri bgp.AddrPrefixInterface) *Destination {
- dest := t.GetDestination(nlri)
- // If destination for given prefix does not exist we create it.
- if dest == nil {
- log.WithFields(log.Fields{
- "Topic": "Table",
- "Nlri": nlri,
- }).Debugf("create Destination")
- dest = NewDestination(nlri, 64)
- t.setDestination(dest)
- }
- return dest
-}
-
-func (t *Table) GetDestinations() map[string]*Destination {
- return t.destinations
-}
-func (t *Table) setDestinations(destinations map[string]*Destination) {
- t.destinations = destinations
-}
-func (t *Table) GetDestination(nlri bgp.AddrPrefixInterface) *Destination {
- dest, ok := t.destinations[t.tableKey(nlri)]
- if ok {
- return dest
- } else {
- return nil
- }
-}
-
-func (t *Table) GetLongerPrefixDestinations(key string) ([]*Destination, error) {
- results := make([]*Destination, 0, len(t.GetDestinations()))
- switch t.routeFamily {
- case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC, bgp.RF_IPv4_MPLS, bgp.RF_IPv6_MPLS:
- _, prefix, err := net.ParseCIDR(key)
- if err != nil {
- return nil, err
- }
- k := CidrToRadixkey(prefix.String())
- r := radix.New()
- for _, dst := range t.GetDestinations() {
- r.Insert(AddrToRadixkey(dst.nlri), dst)
- }
- r.WalkPrefix(k, func(s string, v interface{}) bool {
- results = append(results, v.(*Destination))
- return false
- })
- default:
- for _, dst := range t.GetDestinations() {
- results = append(results, dst)
- }
- }
- return results, nil
-}
-
-func (t *Table) GetEvpnDestinationsWithRouteType(typ string) ([]*Destination, error) {
- var routeType uint8
- switch strings.ToLower(typ) {
- case "a-d":
- routeType = bgp.EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY
- case "macadv":
- routeType = bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT
- case "multicast":
- routeType = bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG
- case "esi":
- routeType = bgp.EVPN_ETHERNET_SEGMENT_ROUTE
- case "prefix":
- routeType = bgp.EVPN_IP_PREFIX
- default:
- return nil, fmt.Errorf("unsupported evpn route type: %s", typ)
- }
- destinations := t.GetDestinations()
- results := make([]*Destination, 0, len(destinations))
- switch t.routeFamily {
- case bgp.RF_EVPN:
- for _, dst := range destinations {
- if nlri, ok := dst.nlri.(*bgp.EVPNNLRI); !ok {
- return nil, fmt.Errorf("invalid evpn nlri type detected: %T", dst.nlri)
- } else if nlri.RouteType == routeType {
- results = append(results, dst)
- }
- }
- default:
- for _, dst := range destinations {
- results = append(results, dst)
- }
- }
- return results, nil
-}
-
-func (t *Table) setDestination(dst *Destination) {
- t.destinations[t.tableKey(dst.nlri)] = dst
-}
-
-func (t *Table) tableKey(nlri bgp.AddrPrefixInterface) string {
- switch T := nlri.(type) {
- case *bgp.IPAddrPrefix:
- b := make([]byte, 5)
- copy(b, T.Prefix.To4())
- b[4] = T.Length
- return *(*string)(unsafe.Pointer(&b))
- case *bgp.IPv6AddrPrefix:
- b := make([]byte, 17)
- copy(b, T.Prefix.To16())
- b[16] = T.Length
- return *(*string)(unsafe.Pointer(&b))
- }
- return nlri.String()
-}
-
-func (t *Table) Bests(id string, as uint32) []*Path {
- paths := make([]*Path, 0, len(t.destinations))
- for _, dst := range t.destinations {
- path := dst.GetBestPath(id, as)
- if path != nil {
- paths = append(paths, path)
- }
- }
- return paths
-}
-
-func (t *Table) MultiBests(id string) [][]*Path {
- paths := make([][]*Path, 0, len(t.destinations))
- for _, dst := range t.destinations {
- path := dst.GetMultiBestPath(id)
- if path != nil {
- paths = append(paths, path)
- }
- }
- return paths
-}
-
-func (t *Table) GetKnownPathList(id string, as uint32) []*Path {
- paths := make([]*Path, 0, len(t.destinations))
- for _, dst := range t.destinations {
- paths = append(paths, dst.GetKnownPathList(id, as)...)
- }
- return paths
-}
-
-func (t *Table) Select(option ...TableSelectOption) (*Table, error) {
- id := GLOBAL_RIB_NAME
- var vrf *Vrf
- adj := false
- prefixes := make([]*LookupPrefix, 0, len(option))
- best := false
- mp := false
- as := uint32(0)
- for _, o := range option {
- if o.ID != "" {
- id = o.ID
- }
- if o.VRF != nil {
- vrf = o.VRF
- }
- adj = o.adj
- prefixes = append(prefixes, o.LookupPrefixes...)
- best = o.Best
- mp = o.MultiPath
- as = o.AS
- }
- dOption := DestinationSelectOption{ID: id, AS: as, VRF: vrf, adj: adj, Best: best, MultiPath: mp}
- r := &Table{
- routeFamily: t.routeFamily,
- destinations: make(map[string]*Destination),
- }
-
- if len(prefixes) != 0 {
- switch t.routeFamily {
- case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC:
- f := func(prefixStr string) bool {
- var nlri bgp.AddrPrefixInterface
- if t.routeFamily == bgp.RF_IPv4_UC {
- nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP, bgp.SAFI_UNICAST, prefixStr)
- } else {
- nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP6, bgp.SAFI_UNICAST, prefixStr)
- }
- if dst := t.GetDestination(nlri); dst != nil {
- if d := dst.Select(dOption); d != nil {
- r.setDestination(d)
- return true
- }
- }
- return false
- }
-
- for _, p := range prefixes {
- key := p.Prefix
- switch p.LookupOption {
- case LOOKUP_LONGER:
- ds, err := t.GetLongerPrefixDestinations(key)
- if err != nil {
- return nil, err
- }
- for _, dst := range ds {
- if d := dst.Select(dOption); d != nil {
- r.setDestination(d)
- }
- }
- case LOOKUP_SHORTER:
- addr, prefix, err := net.ParseCIDR(key)
- if err != nil {
- return nil, err
- }
- ones, _ := prefix.Mask.Size()
- for i := ones; i >= 0; i-- {
- _, prefix, _ := net.ParseCIDR(fmt.Sprintf("%s/%d", addr.String(), i))
- f(prefix.String())
- }
- default:
- if host := net.ParseIP(key); host != nil {
- masklen := 32
- if t.routeFamily == bgp.RF_IPv6_UC {
- masklen = 128
- }
- for i := masklen; i >= 0; i-- {
- _, prefix, err := net.ParseCIDR(fmt.Sprintf("%s/%d", key, i))
- if err != nil {
- return nil, err
- }
- if f(prefix.String()) {
- break
- }
- }
- } else {
- f(key)
- }
- }
- }
- case bgp.RF_EVPN:
- for _, p := range prefixes {
- // Uses LookupPrefix.Prefix as EVPN Route Type string
- ds, err := t.GetEvpnDestinationsWithRouteType(p.Prefix)
- if err != nil {
- return nil, err
- }
- for _, dst := range ds {
- if d := dst.Select(dOption); d != nil {
- r.setDestination(d)
- }
- }
- }
- default:
- return nil, fmt.Errorf("route filtering is not supported for this family")
- }
- } else {
- for _, dst := range t.GetDestinations() {
- if d := dst.Select(dOption); d != nil {
- r.setDestination(d)
- }
- }
- }
- return r, nil
-}
-
-type TableInfo struct {
- NumDestination int
- NumPath int
- NumAccepted int
-}
-
-func (t *Table) Info(id string, as uint32) *TableInfo {
- var numD, numP int
- for _, d := range t.destinations {
- ps := d.GetKnownPathList(id, as)
- if len(ps) > 0 {
- numD += 1
- numP += len(ps)
- }
- }
- return &TableInfo{
- NumDestination: numD,
- NumPath: numP,
- }
-}
diff --git a/table/table_manager.go b/table/table_manager.go
deleted file mode 100644
index 26581cea..00000000
--- a/table/table_manager.go
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright (C) 2014 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 (
- "bytes"
- "fmt"
- "net"
- "time"
-
- farm "github.com/dgryski/go-farm"
- log "github.com/sirupsen/logrus"
-
- "github.com/osrg/gobgp/packet/bgp"
-)
-
-const (
- GLOBAL_RIB_NAME = "global"
-)
-
-func ProcessMessage(m *bgp.BGPMessage, peerInfo *PeerInfo, timestamp time.Time) []*Path {
- update := m.Body.(*bgp.BGPUpdate)
-
- if y, f := update.IsEndOfRib(); y {
- // this message has no normal updates or withdrawals.
- return []*Path{NewEOR(f)}
- }
-
- adds := make([]bgp.AddrPrefixInterface, 0, len(update.NLRI))
- for _, nlri := range update.NLRI {
- adds = append(adds, nlri)
- }
-
- dels := make([]bgp.AddrPrefixInterface, 0, len(update.WithdrawnRoutes))
- for _, nlri := range update.WithdrawnRoutes {
- dels = append(dels, nlri)
- }
-
- attrs := make([]bgp.PathAttributeInterface, 0, len(update.PathAttributes))
- var reach *bgp.PathAttributeMpReachNLRI
- for _, attr := range update.PathAttributes {
- switch a := attr.(type) {
- case *bgp.PathAttributeMpReachNLRI:
- reach = a
- case *bgp.PathAttributeMpUnreachNLRI:
- l := make([]bgp.AddrPrefixInterface, 0, len(a.Value))
- l = append(l, a.Value...)
- dels = append(dels, l...)
- default:
- attrs = append(attrs, attr)
- }
- }
-
- listLen := len(adds) + len(dels)
- if reach != nil {
- listLen += len(reach.Value)
- }
-
- var hash uint32
- if len(adds) > 0 || reach != nil {
- total := bytes.NewBuffer(make([]byte, 0))
- for _, a := range attrs {
- b, _ := a.Serialize()
- total.Write(b)
- }
- hash = farm.Hash32(total.Bytes())
- }
-
- pathList := make([]*Path, 0, listLen)
- for _, nlri := range adds {
- p := NewPath(peerInfo, nlri, false, attrs, timestamp, false)
- p.SetHash(hash)
- pathList = append(pathList, p)
- }
- if reach != nil {
- reachAttrs := make([]bgp.PathAttributeInterface, len(attrs)+1)
- copy(reachAttrs, attrs)
- // we sort attributes when creating a bgp message from paths
- reachAttrs[len(reachAttrs)-1] = reach
-
- for _, nlri := range reach.Value {
- p := NewPath(peerInfo, nlri, false, reachAttrs, timestamp, false)
- p.SetHash(hash)
- pathList = append(pathList, p)
- }
- }
- for _, nlri := range dels {
- p := NewPath(peerInfo, nlri, true, []bgp.PathAttributeInterface{}, timestamp, false)
- pathList = append(pathList, p)
- }
- return pathList
-}
-
-type TableManager struct {
- Tables map[bgp.RouteFamily]*Table
- Vrfs map[string]*Vrf
- rfList []bgp.RouteFamily
-}
-
-func NewTableManager(rfList []bgp.RouteFamily) *TableManager {
- t := &TableManager{
- Tables: make(map[bgp.RouteFamily]*Table),
- Vrfs: make(map[string]*Vrf),
- rfList: rfList,
- }
- for _, rf := range rfList {
- t.Tables[rf] = NewTable(rf)
- }
- return t
-}
-
-func (manager *TableManager) GetRFlist() []bgp.RouteFamily {
- return manager.rfList
-}
-
-func (manager *TableManager) AddVrf(name string, id uint32, rd bgp.RouteDistinguisherInterface, importRt, exportRt []bgp.ExtendedCommunityInterface, info *PeerInfo) ([]*Path, error) {
- if _, ok := manager.Vrfs[name]; ok {
- return nil, fmt.Errorf("vrf %s already exists", name)
- }
- log.WithFields(log.Fields{
- "Topic": "Vrf",
- "Key": name,
- "Rd": rd,
- "ImportRt": importRt,
- "ExportRt": exportRt,
- }).Debugf("add vrf")
- manager.Vrfs[name] = &Vrf{
- Name: name,
- Id: id,
- Rd: rd,
- ImportRt: importRt,
- ExportRt: exportRt,
- }
- msgs := make([]*Path, 0, len(importRt))
- nexthop := "0.0.0.0"
- for _, target := range importRt {
- nlri := bgp.NewRouteTargetMembershipNLRI(info.AS, target)
- pattr := make([]bgp.PathAttributeInterface, 0, 2)
- pattr = append(pattr, bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP))
- pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri}))
- msgs = append(msgs, NewPath(info, nlri, false, pattr, time.Now(), false))
- }
- return msgs, nil
-}
-
-func (manager *TableManager) DeleteVrf(name string) ([]*Path, error) {
- if _, ok := manager.Vrfs[name]; !ok {
- return nil, fmt.Errorf("vrf %s not found", name)
- }
- msgs := make([]*Path, 0)
- vrf := manager.Vrfs[name]
- for _, t := range manager.Tables {
- msgs = append(msgs, t.deletePathsByVrf(vrf)...)
- }
- log.WithFields(log.Fields{
- "Topic": "Vrf",
- "Key": vrf.Name,
- "Rd": vrf.Rd,
- "ImportRt": vrf.ImportRt,
- "ExportRt": vrf.ExportRt,
- }).Debugf("delete vrf")
- delete(manager.Vrfs, name)
- rtcTable := manager.Tables[bgp.RF_RTC_UC]
- msgs = append(msgs, rtcTable.deleteRTCPathsByVrf(vrf, manager.Vrfs)...)
- return msgs, nil
-}
-
-func (tm *TableManager) update(newPath *Path) *Update {
- t := tm.Tables[newPath.GetRouteFamily()]
- t.validatePath(newPath)
- dst := t.getOrCreateDest(newPath.GetNlri())
- u := dst.Calculate(newPath)
- if len(dst.knownPathList) == 0 {
- t.deleteDest(dst)
- }
- return u
-}
-
-func (manager *TableManager) GetPathListByPeer(info *PeerInfo, rf bgp.RouteFamily) []*Path {
- if t, ok := manager.Tables[rf]; ok {
- pathList := make([]*Path, 0, len(t.destinations))
- for _, dst := range t.destinations {
- for _, p := range dst.knownPathList {
- if p.GetSource().Equal(info) {
- pathList = append(pathList, p)
- }
- }
- }
- return pathList
- }
- return nil
-}
-
-func (manager *TableManager) Update(newPath *Path) []*Update {
- if newPath == nil || newPath.IsEOR() {
- return nil
- }
-
- // Except for a special case with EVPN, we'll have one destination.
- updates := make([]*Update, 0, 1)
- family := newPath.GetRouteFamily()
- if _, ok := manager.Tables[family]; ok {
- updates = append(updates, manager.update(newPath))
-
- if family == bgp.RF_EVPN {
- for _, p := range manager.handleMacMobility(newPath) {
- updates = append(updates, manager.update(p))
- }
- }
- }
- return updates
-}
-
-// EVPN MAC MOBILITY HANDLING
-//
-// RFC7432 15. MAC Mobility
-//
-// A PE receiving a MAC/IP Advertisement route for a MAC address with a
-// different Ethernet segment identifier and a higher sequence number
-// than that which it had previously advertised withdraws its MAC/IP
-// Advertisement route.
-func (manager *TableManager) handleMacMobility(path *Path) []*Path {
- pathList := make([]*Path, 0)
- nlri := path.GetNlri().(*bgp.EVPNNLRI)
- if path.IsWithdraw || path.IsLocal() || nlri.RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
- return nil
- }
- for _, path2 := range manager.GetPathList(GLOBAL_RIB_NAME, 0, []bgp.RouteFamily{bgp.RF_EVPN}) {
- if !path2.IsLocal() || path2.GetNlri().(*bgp.EVPNNLRI).RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
- continue
- }
- f := func(p *Path) (bgp.EthernetSegmentIdentifier, net.HardwareAddr, int) {
- nlri := p.GetNlri().(*bgp.EVPNNLRI)
- d := nlri.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute)
- ecs := p.GetExtCommunities()
- seq := -1
- for _, ec := range ecs {
- if t, st := ec.GetTypes(); t == bgp.EC_TYPE_EVPN && st == bgp.EC_SUBTYPE_MAC_MOBILITY {
- seq = int(ec.(*bgp.MacMobilityExtended).Sequence)
- break
- }
- }
- return d.ESI, d.MacAddress, seq
- }
- e1, m1, s1 := f(path)
- e2, m2, s2 := f(path2)
- if bytes.Equal(m1, m2) && !bytes.Equal(e1.Value, e2.Value) && s1 > s2 {
- pathList = append(pathList, path2.Clone(true))
- }
- }
- return pathList
-}
-
-func (manager *TableManager) tables(list ...bgp.RouteFamily) []*Table {
- l := make([]*Table, 0, len(manager.Tables))
- if len(list) == 0 {
- for _, v := range manager.Tables {
- l = append(l, v)
- }
- return l
- }
- for _, f := range list {
- if t, ok := manager.Tables[f]; ok {
- l = append(l, t)
- }
- }
- return l
-}
-
-func (manager *TableManager) getDestinationCount(rfList []bgp.RouteFamily) int {
- count := 0
- for _, t := range manager.tables(rfList...) {
- count += len(t.GetDestinations())
- }
- return count
-}
-
-func (manager *TableManager) GetBestPathList(id string, as uint32, rfList []bgp.RouteFamily) []*Path {
- if SelectionOptions.DisableBestPathSelection {
- // Note: If best path selection disabled, there is no best path.
- return nil
- }
- paths := make([]*Path, 0, manager.getDestinationCount(rfList))
- for _, t := range manager.tables(rfList...) {
- paths = append(paths, t.Bests(id, as)...)
- }
- return paths
-}
-
-func (manager *TableManager) GetBestMultiPathList(id string, rfList []bgp.RouteFamily) [][]*Path {
- if !UseMultiplePaths.Enabled || SelectionOptions.DisableBestPathSelection {
- // Note: If multi path not enabled or best path selection disabled,
- // there is no best multi path.
- return nil
- }
- paths := make([][]*Path, 0, manager.getDestinationCount(rfList))
- for _, t := range manager.tables(rfList...) {
- paths = append(paths, t.MultiBests(id)...)
- }
- return paths
-}
-
-func (manager *TableManager) GetPathList(id string, as uint32, rfList []bgp.RouteFamily) []*Path {
- paths := make([]*Path, 0, manager.getDestinationCount(rfList))
- for _, t := range manager.tables(rfList...) {
- paths = append(paths, t.GetKnownPathList(id, as)...)
- }
- return paths
-}
-
-func (manager *TableManager) GetPathListWithNexthop(id string, rfList []bgp.RouteFamily, nexthop net.IP) []*Path {
- paths := make([]*Path, 0, manager.getDestinationCount(rfList))
- for _, rf := range rfList {
- if t, ok := manager.Tables[rf]; ok {
- for _, path := range t.GetKnownPathList(id, 0) {
- if path.GetNexthop().Equal(nexthop) {
- paths = append(paths, path)
- }
- }
- }
- }
- return paths
-}
-
-func (manager *TableManager) GetDestination(path *Path) *Destination {
- if path == nil {
- return nil
- }
- family := path.GetRouteFamily()
- t, ok := manager.Tables[family]
- if !ok {
- return nil
- }
- return t.GetDestination(path.GetNlri())
-}
-
-func (manager *TableManager) TableInfo(id string, as uint32, family bgp.RouteFamily) (*TableInfo, error) {
- t, ok := manager.Tables[family]
- if !ok {
- return nil, fmt.Errorf("address family %s is not configured", family)
- }
- return t.Info(id, as), nil
-}
diff --git a/table/table_manager_test.go b/table/table_manager_test.go
deleted file mode 100644
index 11a7b066..00000000
--- a/table/table_manager_test.go
+++ /dev/null
@@ -1,2281 +0,0 @@
-// Copyright (C) 2014 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"
- "net"
- "testing"
- "time"
-
- "github.com/osrg/gobgp/packet/bgp"
- "github.com/stretchr/testify/assert"
-)
-
-// process BGPUpdate message
-// this function processes only BGPUpdate
-func (manager *TableManager) ProcessUpdate(fromPeer *PeerInfo, message *bgp.BGPMessage) ([]*Path, error) {
- pathList := make([]*Path, 0)
- dsts := make([]*Update, 0)
- for _, path := range ProcessMessage(message, fromPeer, time.Now()) {
- dsts = append(dsts, manager.Update(path)...)
- }
- for _, d := range dsts {
- b, _, _ := d.GetChanges(GLOBAL_RIB_NAME, 0, false)
- pathList = append(pathList, b)
- }
- return pathList, nil
-}
-
-func peerR1() *PeerInfo {
- peer := &PeerInfo{
- AS: 65000,
- LocalAS: 65000,
- ID: net.ParseIP("10.0.0.3").To4(),
- LocalID: net.ParseIP("10.0.0.1").To4(),
- Address: net.ParseIP("10.0.0.1").To4(),
- }
- return peer
-}
-
-func peerR2() *PeerInfo {
- peer := &PeerInfo{
- AS: 65100,
- LocalAS: 65000,
- Address: net.ParseIP("10.0.0.2").To4(),
- }
- return peer
-}
-
-func peerR3() *PeerInfo {
- peer := &PeerInfo{
- AS: 65000,
- LocalAS: 65000,
- ID: net.ParseIP("10.0.0.2").To4(),
- LocalID: net.ParseIP("10.0.0.1").To4(),
- Address: net.ParseIP("10.0.0.3").To4(),
- }
- return peer
-}
-
-// test best path calculation and check the result path is from R1
-func TestProcessBGPUpdate_0_select_onlypath_ipv4(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv4_UC})
-
- bgpMessage := update_fromR1()
- peer := peerR1()
- pList, err := tm.ProcessUpdate(peer, bgpMessage)
- assert.Equal(t, len(pList), 1)
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv4_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage.Body.(*bgp.BGPUpdate).PathAttributes
- expectedOrigin := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedNexthopAttr := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- pathNexthop := attr.(*bgp.PathAttributeNextHop)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, 4, len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "10.10.10.0/24"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "192.168.50.1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-// test best path calculation and check the result path is from R1
-func TestProcessBGPUpdate_0_select_onlypath_ipv6(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv6_UC})
-
- bgpMessage := update_fromR1_ipv6()
- peer := peerR1()
- pList, err := tm.ProcessUpdate(peer, bgpMessage)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv6_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, 4, len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "2001:123:123:1::/64"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "2001::192:168:50:1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-// test: compare localpref
-func TestProcessBGPUpdate_1_select_high_localpref_ipv4(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv4_UC})
-
- // low localpref message
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000})
- nexthop1 := bgp.NewPathAttributeNextHop("192.168.50.1")
- med1 := bgp.NewPathAttributeMultiExitDisc(0)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- origin1, aspath1, nexthop1, med1, localpref1,
- }
- nlri1 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nlri1)
-
- // high localpref message
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65100, 65000})
- nexthop2 := bgp.NewPathAttributeNextHop("192.168.50.1")
- med2 := bgp.NewPathAttributeMultiExitDisc(100)
- localpref2 := bgp.NewPathAttributeLocalPref(200)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- origin2, aspath2, nexthop2, med2, localpref2,
- }
- nlri2 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri2)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- peer2 := peerR2()
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv4_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
- expectedOrigin := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedNexthopAttr := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- pathNexthop := attr.(*bgp.PathAttributeNextHop)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes2), len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "10.10.10.0/24"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "192.168.50.1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-func TestProcessBGPUpdate_1_select_high_localpref_ipv6(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv6_UC})
-
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000})
- mp_reach1 := createMpReach("2001::192:168:50:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med1 := bgp.NewPathAttributeMultiExitDisc(100)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- mp_reach1, origin1, aspath1, med1, localpref1,
- }
-
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nil)
-
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65100, 65000})
- mp_reach2 := createMpReach("2001::192:168:100:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med2 := bgp.NewPathAttributeMultiExitDisc(100)
- localpref2 := bgp.NewPathAttributeLocalPref(200)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- mp_reach2, origin2, aspath2, med2, localpref2,
- }
-
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nil)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- peer2 := peerR2()
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv6_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, 5, len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "2001:123:123:1::/64"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "2001::192:168:100:1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-// test: compare localOrigin
-func TestProcessBGPUpdate_2_select_local_origin_ipv4(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv4_UC})
-
- // low localpref message
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000})
- nexthop1 := bgp.NewPathAttributeNextHop("192.168.50.1")
- med1 := bgp.NewPathAttributeMultiExitDisc(0)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- origin1, aspath1, nexthop1, med1, localpref1,
- }
- nlri1 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nlri1)
-
- // high localpref message
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{})
- nexthop2 := bgp.NewPathAttributeNextHop("0.0.0.0")
- med2 := bgp.NewPathAttributeMultiExitDisc(100)
- localpref2 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- origin2, aspath2, nexthop2, med2, localpref2,
- }
- nlri2 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri2)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- var peer2 *PeerInfo = &PeerInfo{
- Address: net.ParseIP("0.0.0.0"),
- }
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv4_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
- expectedOrigin := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedNexthopAttr := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- pathNexthop := attr.(*bgp.PathAttributeNextHop)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes2), len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "10.10.10.0/24"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "0.0.0.0"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-func TestProcessBGPUpdate_2_select_local_origin_ipv6(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv6_UC})
-
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000})
- mp_reach1 := createMpReach("2001::192:168:50:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med1 := bgp.NewPathAttributeMultiExitDisc(100)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- mp_reach1, origin1, aspath1, med1, localpref1,
- }
-
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nil)
-
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{})
- mp_reach2 := createMpReach("::",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med2 := bgp.NewPathAttributeMultiExitDisc(100)
- localpref2 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- mp_reach2, origin2, aspath2, med2, localpref2,
- }
-
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nil)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- var peer2 *PeerInfo = &PeerInfo{
- Address: net.ParseIP("0.0.0.0"),
- }
-
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv6_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, 5, len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "2001:123:123:1::/64"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "::"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-// test: compare AS_PATH
-func TestProcessBGPUpdate_3_select_aspath_ipv4(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv4_UC})
-
- bgpMessage1 := update_fromR2viaR1()
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
- bgpMessage2 := update_fromR2()
- peer2 := peerR2()
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv4_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
- expectedOrigin := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedNexthopAttr := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- pathNexthop := attr.(*bgp.PathAttributeNextHop)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, 4, len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "20.20.20.0/24"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "192.168.100.1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-func TestProcessBGPUpdate_3_select_aspath_ipv6(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv6_UC})
-
- bgpMessage1 := update_fromR2viaR1_ipv6()
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
- bgpMessage2 := update_fromR2_ipv6()
- peer2 := peerR2()
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv6_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, 4, len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "2002:223:123:1::/64"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "2001::192:168:100:1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-// test: compare Origin
-func TestProcessBGPUpdate_4_select_low_origin_ipv4(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv4_UC})
-
- // low origin message
- origin1 := bgp.NewPathAttributeOrigin(1)
- aspath1 := createAsPathAttribute([]uint32{65200, 65000})
- nexthop1 := bgp.NewPathAttributeNextHop("192.168.50.1")
- med1 := bgp.NewPathAttributeMultiExitDisc(100)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- origin1, aspath1, nexthop1, med1, localpref1,
- }
- nlri1 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nlri1)
-
- // high origin message
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65100, 65000})
- nexthop2 := bgp.NewPathAttributeNextHop("192.168.100.1")
- med2 := bgp.NewPathAttributeMultiExitDisc(100)
- localpref2 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- origin2, aspath2, nexthop2, med2, localpref2,
- }
- nlri2 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri2)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- peer2 := peerR2()
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv4_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
- expectedOrigin := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedNexthopAttr := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- pathNexthop := attr.(*bgp.PathAttributeNextHop)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes2), len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "10.10.10.0/24"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "192.168.100.1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-func TestProcessBGPUpdate_4_select_low_origin_ipv6(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv6_UC})
-
- origin1 := bgp.NewPathAttributeOrigin(1)
- aspath1 := createAsPathAttribute([]uint32{65200, 65000})
- mp_reach1 := createMpReach("2001::192:168:50:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med1 := bgp.NewPathAttributeMultiExitDisc(100)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- mp_reach1, origin1, aspath1, med1, localpref1,
- }
-
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nil)
-
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65100, 65000})
- mp_reach2 := createMpReach("2001::192:168:100:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med2 := bgp.NewPathAttributeMultiExitDisc(100)
- localpref2 := bgp.NewPathAttributeLocalPref(200)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- mp_reach2, origin2, aspath2, med2, localpref2,
- }
-
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nil)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- peer2 := peerR2()
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv6_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, 5, len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "2001:123:123:1::/64"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "2001::192:168:100:1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-// test: compare MED
-func TestProcessBGPUpdate_5_select_low_med_ipv4(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv4_UC})
-
- // low origin message
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65200, 65000})
- nexthop1 := bgp.NewPathAttributeNextHop("192.168.50.1")
- med1 := bgp.NewPathAttributeMultiExitDisc(500)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- origin1, aspath1, nexthop1, med1, localpref1,
- }
- nlri1 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nlri1)
-
- // high origin message
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65100, 65000})
- nexthop2 := bgp.NewPathAttributeNextHop("192.168.100.1")
- med2 := bgp.NewPathAttributeMultiExitDisc(100)
- localpref2 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- origin2, aspath2, nexthop2, med2, localpref2,
- }
- nlri2 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri2)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- peer2 := peerR2()
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv4_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
- expectedOrigin := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedNexthopAttr := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- pathNexthop := attr.(*bgp.PathAttributeNextHop)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes2), len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "10.10.10.0/24"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "192.168.100.1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-func TestProcessBGPUpdate_5_select_low_med_ipv6(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv6_UC})
-
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65200, 65000})
- mp_reach1 := createMpReach("2001::192:168:50:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med1 := bgp.NewPathAttributeMultiExitDisc(500)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- mp_reach1, origin1, aspath1, med1, localpref1,
- }
-
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nil)
-
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65100, 65000})
- mp_reach2 := createMpReach("2001::192:168:100:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med2 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref2 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- mp_reach2, origin2, aspath2, med2, localpref2,
- }
-
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nil)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- peer2 := peerR2()
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv6_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, 5, len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "2001:123:123:1::/64"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "2001::192:168:100:1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-// test: compare AS_NUMBER(prefer eBGP path)
-func TestProcessBGPUpdate_6_select_ebgp_path_ipv4(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv4_UC})
-
- // low origin message
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000, 65200})
- nexthop1 := bgp.NewPathAttributeNextHop("192.168.50.1")
- med1 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- origin1, aspath1, nexthop1, med1, localpref1,
- }
- nlri1 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nlri1)
-
- // high origin message
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65100, 65000})
- nexthop2 := bgp.NewPathAttributeNextHop("192.168.100.1")
- med2 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref2 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- origin2, aspath2, nexthop2, med2, localpref2,
- }
- nlri2 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri2)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- peer2 := peerR2()
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv4_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
- expectedOrigin := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedNexthopAttr := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- pathNexthop := attr.(*bgp.PathAttributeNextHop)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes2), len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "10.10.10.0/24"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "192.168.100.1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-func TestProcessBGPUpdate_6_select_ebgp_path_ipv6(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv6_UC})
-
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000, 65200})
- mp_reach1 := createMpReach("2001::192:168:50:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med1 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- mp_reach1, origin1, aspath1, med1, localpref1,
- }
-
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nil)
-
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65100, 65200})
- mp_reach2 := createMpReach("2001::192:168:100:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med2 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref2 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- mp_reach2, origin2, aspath2, med2, localpref2,
- }
-
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nil)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- peer2 := peerR2()
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv6_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, 5, len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "2001:123:123:1::/64"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "2001::192:168:100:1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-// test: compare IGP cost -> N/A
-
-// test: compare Router ID
-func TestProcessBGPUpdate_7_select_low_routerid_path_ipv4(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv4_UC})
- SelectionOptions.ExternalCompareRouterId = true
-
- // low origin message
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000, 65200})
- nexthop1 := bgp.NewPathAttributeNextHop("192.168.50.1")
- med1 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- origin1, aspath1, nexthop1, med1, localpref1,
- }
- nlri1 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nlri1)
-
- // high origin message
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65000, 65100})
- nexthop2 := bgp.NewPathAttributeNextHop("192.168.100.1")
- med2 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref2 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- origin2, aspath2, nexthop2, med2, localpref2,
- }
- nlri2 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri2)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- peer3 := peerR3()
- pList, err = tm.ProcessUpdate(peer3, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv4_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
- expectedOrigin := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedNexthopAttr := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- pathNexthop := attr.(*bgp.PathAttributeNextHop)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes2), len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "10.10.10.0/24"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "192.168.100.1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-func TestProcessBGPUpdate_7_select_low_routerid_path_ipv6(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv6_UC})
-
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000, 65200})
- mp_reach1 := createMpReach("2001::192:168:50:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med1 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- mp_reach1, origin1, aspath1, med1, localpref1,
- }
-
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nil)
-
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65100, 65200})
- mp_reach2 := createMpReach("2001::192:168:100:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med2 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref2 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- mp_reach2, origin2, aspath2, med2, localpref2,
- }
-
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nil)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- peer3 := peerR3()
- pList, err = tm.ProcessUpdate(peer3, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv6_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, 5, len(path.GetPathAttrs()))
-
- // check destination
- expectedPrefix := "2001:123:123:1::/64"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "2001::192:168:100:1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-// test: withdraw and mpunreach path
-func TestProcessBGPUpdate_8_withdraw_path_ipv4(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv4_UC})
-
- // path1
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000})
- nexthop1 := bgp.NewPathAttributeNextHop("192.168.50.1")
- med1 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- origin1, aspath1, nexthop1, med1, localpref1,
- }
- nlri1 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nlri1)
-
- // path 2
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65100, 65000})
- nexthop2 := bgp.NewPathAttributeNextHop("192.168.100.1")
- med2 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref2 := bgp.NewPathAttributeLocalPref(200)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- origin2, aspath2, nexthop2, med2, localpref2,
- }
- nlri2 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri2)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- peer2 := peerR2()
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv4_UC)
-
- // check PathAttribute
- checkPattr := func(expected *bgp.BGPMessage, actual *Path) {
- pathAttributes := expected.Body.(*bgp.BGPUpdate).PathAttributes
- expectedOrigin := pathAttributes[0]
- attr := actual.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedNexthopAttr := pathAttributes[2]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- pathNexthop := attr.(*bgp.PathAttributeNextHop)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedMed := pathAttributes[3]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes), len(path.GetPathAttrs()))
- }
- checkPattr(bgpMessage2, path)
- // check destination
- expectedPrefix := "10.10.10.0/24"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "192.168.100.1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
- //withdraw path
- w1 := bgp.NewIPAddrPrefix(24, "10.10.10.0")
- w := []*bgp.IPAddrPrefix{w1}
- bgpMessage3 := bgp.NewBGPUpdateMessage(w, nil, nil)
-
- pList, err = tm.ProcessUpdate(peer2, bgpMessage3)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- path = pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv4_UC)
-
- checkPattr(bgpMessage1, path)
- // check destination
- expectedPrefix = "10.10.10.0/24"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop = "192.168.50.1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-}
-
-// TODO MP_UNREACH
-func TestProcessBGPUpdate_8_mpunreach_path_ipv6(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv6_UC})
-
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000})
- mp_reach1 := createMpReach("2001::192:168:50:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med1 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- mp_reach1, origin1, aspath1, med1, localpref1,
- }
-
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nil)
-
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65100, 65000})
- mp_reach2 := createMpReach("2001::192:168:100:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med2 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref2 := bgp.NewPathAttributeLocalPref(200)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- mp_reach2, origin2, aspath2, med2, localpref2,
- }
-
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nil)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- peer2 := peerR2()
- pList, err = tm.ProcessUpdate(peer2, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv6_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute
- checkPattr := func(expected *bgp.BGPMessage, actual *Path) {
- pathAttributes := expected.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes), len(path.GetPathAttrs()))
- }
-
- checkPattr(bgpMessage2, path)
-
- // check destination
- expectedPrefix := "2001:123:123:1::/64"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "2001::192:168:100:1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
- //mpunreach path
- mp_unreach := createMpUNReach("2001:123:123:1::", 64)
- bgpMessage3 := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{mp_unreach}, nil)
-
- pList, err = tm.ProcessUpdate(peer2, bgpMessage3)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- path = pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv6_UC)
-
- checkPattr(bgpMessage1, path)
- // check destination
- expectedPrefix = "2001:123:123:1::/64"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop = "2001::192:168:50:1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-// handle bestpath lost
-func TestProcessBGPUpdate_bestpath_lost_ipv4(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv4_UC})
-
- // path1
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000})
- nexthop1 := bgp.NewPathAttributeNextHop("192.168.50.1")
- med1 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- origin1, aspath1, nexthop1, med1, localpref1,
- }
- nlri1 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nlri1)
-
- // path 1 withdraw
- w1 := bgp.NewIPAddrPrefix(24, "10.10.10.0")
- w := []*bgp.IPAddrPrefix{w1}
- bgpMessage1_w := bgp.NewBGPUpdateMessage(w, nil, nil)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- pList, err = tm.ProcessUpdate(peer1, bgpMessage1_w)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, true)
- assert.NoError(t, err)
-
- // check old best path
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv4_UC)
-
- // check PathAttribute
- checkPattr := func(expected *bgp.BGPMessage, actual *Path) {
- pathAttributes := expected.Body.(*bgp.BGPUpdate).PathAttributes
- expectedOrigin := pathAttributes[0]
- attr := actual.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedNexthopAttr := pathAttributes[2]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- pathNexthop := attr.(*bgp.PathAttributeNextHop)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedMed := pathAttributes[3]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes), len(path.GetPathAttrs()))
- }
-
- checkPattr(bgpMessage1, path)
- // check destination
- expectedPrefix := "10.10.10.0/24"
- assert.Equal(t, expectedPrefix, path.getPrefix())
-}
-
-func TestProcessBGPUpdate_bestpath_lost_ipv6(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv6_UC})
-
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000})
- mp_reach1 := createMpReach("2001::192:168:50:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med1 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- mp_reach1, origin1, aspath1, med1, localpref1,
- }
-
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nil)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // path1 mpunreach
- mp_unreach := createMpUNReach("2001:123:123:1::", 64)
- bgpMessage1_w := bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{mp_unreach}, nil)
-
- pList, err = tm.ProcessUpdate(peer1, bgpMessage1_w)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, true)
- assert.NoError(t, err)
-
- // check old best path
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv6_UC)
-
- // check PathAttribute
- checkPattr := func(expected *bgp.BGPMessage, actual *Path) {
- pathAttributes := expected.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr := actual.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes), len(path.GetPathAttrs()))
- }
-
- checkPattr(bgpMessage1, path)
-
- // check destination
- expectedPrefix := "2001:123:123:1::/64"
- assert.Equal(t, expectedPrefix, path.getPrefix())
-}
-
-// test: implicit withdrawal case
-func TestProcessBGPUpdate_implicit_withdrwal_ipv4(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv4_UC})
-
- // path1
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000, 65100, 65200})
- nexthop1 := bgp.NewPathAttributeNextHop("192.168.50.1")
- med1 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref1 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- origin1, aspath1, nexthop1, med1, localpref1,
- }
- nlri1 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nlri1)
-
- // path 1 from same peer but short AS_PATH
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65000, 65100})
- nexthop2 := bgp.NewPathAttributeNextHop("192.168.50.1")
- med2 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref2 := bgp.NewPathAttributeLocalPref(100)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- origin2, aspath2, nexthop2, med2, localpref2,
- }
- nlri2 := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri2)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- pList, err = tm.ProcessUpdate(peer1, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv4_UC)
-
- // check PathAttribute
- checkPattr := func(expected *bgp.BGPMessage, actual *Path) {
- pathAttributes := expected.Body.(*bgp.BGPUpdate).PathAttributes
- expectedOrigin := pathAttributes[0]
- attr := actual.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedNexthopAttr := pathAttributes[2]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- pathNexthop := attr.(*bgp.PathAttributeNextHop)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedMed := pathAttributes[3]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes), len(path.GetPathAttrs()))
- }
- checkPattr(bgpMessage2, path)
- // check destination
- expectedPrefix := "10.10.10.0/24"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "192.168.50.1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-func TestProcessBGPUpdate_implicit_withdrwal_ipv6(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv6_UC})
-
- origin1 := bgp.NewPathAttributeOrigin(0)
- aspath1 := createAsPathAttribute([]uint32{65000, 65100, 65200})
- mp_reach1 := createMpReach("2001::192:168:50:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med1 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref1 := bgp.NewPathAttributeLocalPref(200)
-
- pathAttributes1 := []bgp.PathAttributeInterface{
- mp_reach1, origin1, aspath1, med1, localpref1,
- }
-
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nil)
-
- origin2 := bgp.NewPathAttributeOrigin(0)
- aspath2 := createAsPathAttribute([]uint32{65000, 65100})
- mp_reach2 := createMpReach("2001::192:168:50:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")})
- med2 := bgp.NewPathAttributeMultiExitDisc(200)
- localpref2 := bgp.NewPathAttributeLocalPref(200)
-
- pathAttributes2 := []bgp.PathAttributeInterface{
- mp_reach2, origin2, aspath2, med2, localpref2,
- }
-
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nil)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- pList, err = tm.ProcessUpdate(peer1, bgpMessage2)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check type
- path := pList[0]
- assert.Equal(t, path.GetRouteFamily(), bgp.RF_IPv6_UC)
-
- // check PathAttribute
- pathAttributes := bgpMessage2.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute
- checkPattr := func(expected *bgp.BGPMessage, actual *Path) {
- pathAttributes := expected.Body.(*bgp.BGPUpdate).PathAttributes
-
- expectedNexthopAttr := pathAttributes[0]
- attr := actual.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- pathNexthop := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[1]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[2]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[3]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes), len(path.GetPathAttrs()))
- }
-
- checkPattr(bgpMessage2, path)
-
- // check destination
- expectedPrefix := "2001:123:123:1::/64"
- assert.Equal(t, expectedPrefix, path.getPrefix())
- // check nexthop
- expectedNexthop := "2001::192:168:50:1"
- assert.Equal(t, expectedNexthop, path.GetNexthop().String())
-
-}
-
-// check multiple paths
-func TestProcessBGPUpdate_multiple_nlri_ipv4(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv4_UC})
-
- createPathAttr := func(aspaths []uint32, nh string) []bgp.PathAttributeInterface {
- origin := bgp.NewPathAttributeOrigin(0)
- aspath := createAsPathAttribute(aspaths)
- nexthop := bgp.NewPathAttributeNextHop(nh)
- med := bgp.NewPathAttributeMultiExitDisc(200)
- localpref := bgp.NewPathAttributeLocalPref(100)
- pathAttr := []bgp.PathAttributeInterface{
- origin, aspath, nexthop, med, localpref,
- }
- return pathAttr
- }
-
- // check PathAttribute
- checkPattr := func(expected *bgp.BGPMessage, actual *Path) {
- pathAttributes := expected.Body.(*bgp.BGPUpdate).PathAttributes
- expectedOrigin := pathAttributes[0]
- attr := actual.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedNexthopAttr := pathAttributes[2]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
- pathNexthop := attr.(*bgp.PathAttributeNextHop)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedMed := pathAttributes[3]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes), len(actual.GetPathAttrs()))
- }
-
- checkBestPathResult := func(rf bgp.RouteFamily, prefix, nexthop string, p *Path, m *bgp.BGPMessage) {
- assert.Equal(t, p.GetRouteFamily(), rf)
- checkPattr(m, p)
- // check destination
- assert.Equal(t, prefix, p.getPrefix())
- // check nexthop
- assert.Equal(t, nexthop, p.GetNexthop().String())
- }
-
- // path1
- pathAttributes1 := createPathAttr([]uint32{65000, 65100, 65200}, "192.168.50.1")
- nlri1 := []*bgp.IPAddrPrefix{
- bgp.NewIPAddrPrefix(24, "10.10.10.0"),
- bgp.NewIPAddrPrefix(24, "20.20.20.0"),
- bgp.NewIPAddrPrefix(24, "30.30.30.0"),
- bgp.NewIPAddrPrefix(24, "40.40.40.0"),
- bgp.NewIPAddrPrefix(24, "50.50.50.0")}
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nlri1)
-
- // path2
- pathAttributes2 := createPathAttr([]uint32{65000, 65100, 65300}, "192.168.50.1")
- nlri2 := []*bgp.IPAddrPrefix{
- bgp.NewIPAddrPrefix(24, "11.11.11.0"),
- bgp.NewIPAddrPrefix(24, "22.22.22.0"),
- bgp.NewIPAddrPrefix(24, "33.33.33.0"),
- bgp.NewIPAddrPrefix(24, "44.44.44.0"),
- bgp.NewIPAddrPrefix(24, "55.55.55.0")}
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri2)
-
- // path3
- pathAttributes3 := createPathAttr([]uint32{65000, 65100, 65400}, "192.168.50.1")
- nlri3 := []*bgp.IPAddrPrefix{
- bgp.NewIPAddrPrefix(24, "77.77.77.0"),
- bgp.NewIPAddrPrefix(24, "88.88.88.0"),
- }
- bgpMessage3 := bgp.NewBGPUpdateMessage(nil, pathAttributes3, nlri3)
-
- // path4
- pathAttributes4 := createPathAttr([]uint32{65000, 65100, 65500}, "192.168.50.1")
- nlri4 := []*bgp.IPAddrPrefix{
- bgp.NewIPAddrPrefix(24, "99.99.99.0"),
- }
- bgpMessage4 := bgp.NewBGPUpdateMessage(nil, pathAttributes4, nlri4)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 5, len(pList))
- for _, p := range pList {
- assert.Equal(t, p.IsWithdraw, false)
- }
- assert.NoError(t, err)
-
- checkBestPathResult(bgp.RF_IPv4_UC, "10.10.10.0/24", "192.168.50.1", pList[0], bgpMessage1)
- checkBestPathResult(bgp.RF_IPv4_UC, "20.20.20.0/24", "192.168.50.1", pList[1], bgpMessage1)
- checkBestPathResult(bgp.RF_IPv4_UC, "30.30.30.0/24", "192.168.50.1", pList[2], bgpMessage1)
- checkBestPathResult(bgp.RF_IPv4_UC, "40.40.40.0/24", "192.168.50.1", pList[3], bgpMessage1)
- checkBestPathResult(bgp.RF_IPv4_UC, "50.50.50.0/24", "192.168.50.1", pList[4], bgpMessage1)
-
- pList, err = tm.ProcessUpdate(peer1, bgpMessage2)
- assert.Equal(t, 5, len(pList))
- for _, p := range pList {
- assert.Equal(t, p.IsWithdraw, false)
- }
- assert.NoError(t, err)
-
- checkBestPathResult(bgp.RF_IPv4_UC, "11.11.11.0/24", "192.168.50.1", pList[0], bgpMessage2)
- checkBestPathResult(bgp.RF_IPv4_UC, "22.22.22.0/24", "192.168.50.1", pList[1], bgpMessage2)
- checkBestPathResult(bgp.RF_IPv4_UC, "33.33.33.0/24", "192.168.50.1", pList[2], bgpMessage2)
- checkBestPathResult(bgp.RF_IPv4_UC, "44.44.44.0/24", "192.168.50.1", pList[3], bgpMessage2)
- checkBestPathResult(bgp.RF_IPv4_UC, "55.55.55.0/24", "192.168.50.1", pList[4], bgpMessage2)
-
- pList, err = tm.ProcessUpdate(peer1, bgpMessage3)
- assert.Equal(t, 2, len(pList))
- for _, p := range pList {
- assert.Equal(t, p.IsWithdraw, false)
- }
- assert.NoError(t, err)
-
- pList, err = tm.ProcessUpdate(peer1, bgpMessage4)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check table
- table := tm.Tables[bgp.RF_IPv4_UC]
- assert.Equal(t, 13, len(table.GetDestinations()))
-
-}
-
-// check multiple paths
-func TestProcessBGPUpdate_multiple_nlri_ipv6(t *testing.T) {
-
- tm := NewTableManager([]bgp.RouteFamily{bgp.RF_IPv6_UC})
-
- createPathAttr := func(aspaths []uint32) []bgp.PathAttributeInterface {
- origin := bgp.NewPathAttributeOrigin(0)
- aspath := createAsPathAttribute(aspaths)
- med := bgp.NewPathAttributeMultiExitDisc(100)
- localpref := bgp.NewPathAttributeLocalPref(100)
- pathAttr := []bgp.PathAttributeInterface{
- origin, aspath, med, localpref,
- }
- return pathAttr
- }
-
- // check PathAttribute
- checkPattr := func(expected *bgp.BGPMessage, actual *Path) {
- pathAttributes := expected.Body.(*bgp.BGPUpdate).PathAttributes
- pathNexthop := pathAttributes[4]
- attr := actual.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- expectedNexthopAttr := attr.(*bgp.PathAttributeMpReachNLRI)
- assert.Equal(t, expectedNexthopAttr, pathNexthop)
-
- expectedOrigin := pathAttributes[0]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN)
- pathOrigin := attr.(*bgp.PathAttributeOrigin)
- assert.Equal(t, expectedOrigin, pathOrigin)
-
- expectedAsPath := pathAttributes[1]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
- pathAspath := attr.(*bgp.PathAttributeAsPath)
- assert.Equal(t, expectedAsPath, pathAspath)
-
- expectedMed := pathAttributes[2]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
- pathMed := attr.(*bgp.PathAttributeMultiExitDisc)
- assert.Equal(t, expectedMed, pathMed)
-
- expectedLocalpref := pathAttributes[3]
- attr = actual.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF)
- localpref := attr.(*bgp.PathAttributeLocalPref)
- assert.Equal(t, expectedLocalpref, localpref)
-
- // check PathAttribute length
- assert.Equal(t, len(pathAttributes), len(actual.GetPathAttrs()))
-
- }
-
- checkBestPathResult := func(rf bgp.RouteFamily, prefix, nexthop string, p *Path, m *bgp.BGPMessage) {
- assert.Equal(t, p.GetRouteFamily(), rf)
- checkPattr(m, p)
- // check destination
- assert.Equal(t, prefix, p.getPrefix())
- // check nexthop
- assert.Equal(t, nexthop, p.GetNexthop().String())
- }
-
- // path1
- pathAttributes1 := createPathAttr([]uint32{65000, 65100, 65200})
- mpreach1 := createMpReach("2001::192:168:50:1", []bgp.AddrPrefixInterface{
- bgp.NewIPv6AddrPrefix(64, "2001:123:1210:11::"),
- bgp.NewIPv6AddrPrefix(64, "2001:123:1220:11::"),
- bgp.NewIPv6AddrPrefix(64, "2001:123:1230:11::"),
- bgp.NewIPv6AddrPrefix(64, "2001:123:1240:11::"),
- bgp.NewIPv6AddrPrefix(64, "2001:123:1250:11::"),
- })
- pathAttributes1 = append(pathAttributes1, mpreach1)
- bgpMessage1 := bgp.NewBGPUpdateMessage(nil, pathAttributes1, nil)
-
- // path2
- pathAttributes2 := createPathAttr([]uint32{65000, 65100, 65300})
- mpreach2 := createMpReach("2001::192:168:50:1", []bgp.AddrPrefixInterface{
- bgp.NewIPv6AddrPrefix(64, "2001:123:1211:11::"),
- bgp.NewIPv6AddrPrefix(64, "2001:123:1222:11::"),
- bgp.NewIPv6AddrPrefix(64, "2001:123:1233:11::"),
- bgp.NewIPv6AddrPrefix(64, "2001:123:1244:11::"),
- bgp.NewIPv6AddrPrefix(64, "2001:123:1255:11::"),
- })
- pathAttributes2 = append(pathAttributes2, mpreach2)
- bgpMessage2 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nil)
-
- // path3
- pathAttributes3 := createPathAttr([]uint32{65000, 65100, 65400})
- mpreach3 := createMpReach("2001::192:168:50:1", []bgp.AddrPrefixInterface{
- bgp.NewIPv6AddrPrefix(64, "2001:123:1277:11::"),
- bgp.NewIPv6AddrPrefix(64, "2001:123:1288:11::"),
- })
- pathAttributes3 = append(pathAttributes3, mpreach3)
- bgpMessage3 := bgp.NewBGPUpdateMessage(nil, pathAttributes3, nil)
-
- // path4
- pathAttributes4 := createPathAttr([]uint32{65000, 65100, 65500})
- mpreach4 := createMpReach("2001::192:168:50:1", []bgp.AddrPrefixInterface{
- bgp.NewIPv6AddrPrefix(64, "2001:123:1299:11::"),
- })
- pathAttributes4 = append(pathAttributes4, mpreach4)
- bgpMessage4 := bgp.NewBGPUpdateMessage(nil, pathAttributes4, nil)
-
- peer1 := peerR1()
- pList, err := tm.ProcessUpdate(peer1, bgpMessage1)
- assert.Equal(t, 5, len(pList))
- for _, p := range pList {
- assert.Equal(t, p.IsWithdraw, false)
- }
- assert.NoError(t, err)
-
- checkBestPathResult(bgp.RF_IPv6_UC, "2001:123:1210:11::/64", "2001::192:168:50:1", pList[0], bgpMessage1)
- checkBestPathResult(bgp.RF_IPv6_UC, "2001:123:1220:11::/64", "2001::192:168:50:1", pList[1], bgpMessage1)
- checkBestPathResult(bgp.RF_IPv6_UC, "2001:123:1230:11::/64", "2001::192:168:50:1", pList[2], bgpMessage1)
- checkBestPathResult(bgp.RF_IPv6_UC, "2001:123:1240:11::/64", "2001::192:168:50:1", pList[3], bgpMessage1)
- checkBestPathResult(bgp.RF_IPv6_UC, "2001:123:1250:11::/64", "2001::192:168:50:1", pList[4], bgpMessage1)
-
- pList, err = tm.ProcessUpdate(peer1, bgpMessage2)
- assert.Equal(t, 5, len(pList))
- for _, p := range pList {
- assert.Equal(t, p.IsWithdraw, false)
- }
- assert.NoError(t, err)
-
- checkBestPathResult(bgp.RF_IPv6_UC, "2001:123:1211:11::/64", "2001::192:168:50:1", pList[0], bgpMessage2)
- checkBestPathResult(bgp.RF_IPv6_UC, "2001:123:1222:11::/64", "2001::192:168:50:1", pList[1], bgpMessage2)
- checkBestPathResult(bgp.RF_IPv6_UC, "2001:123:1233:11::/64", "2001::192:168:50:1", pList[2], bgpMessage2)
- checkBestPathResult(bgp.RF_IPv6_UC, "2001:123:1244:11::/64", "2001::192:168:50:1", pList[3], bgpMessage2)
- checkBestPathResult(bgp.RF_IPv6_UC, "2001:123:1255:11::/64", "2001::192:168:50:1", pList[4], bgpMessage2)
-
- pList, err = tm.ProcessUpdate(peer1, bgpMessage3)
- assert.Equal(t, 2, len(pList))
- for _, p := range pList {
- assert.Equal(t, p.IsWithdraw, false)
- }
- assert.NoError(t, err)
-
- pList, err = tm.ProcessUpdate(peer1, bgpMessage4)
- assert.Equal(t, 1, len(pList))
- assert.Equal(t, pList[0].IsWithdraw, false)
- assert.NoError(t, err)
-
- // check table
- table := tm.Tables[bgp.RF_IPv6_UC]
- assert.Equal(t, 13, len(table.GetDestinations()))
-
-}
-
-func TestProcessBGPUpdate_Timestamp(t *testing.T) {
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65000})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
-
- adjRib := NewAdjRib([]bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv6_UC})
- m1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- peer := peerR1()
- pList1 := ProcessMessage(m1, peer, time.Now())
- path1 := pList1[0]
- t1 := path1.GetTimestamp()
- adjRib.Update(pList1)
-
- m2 := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
- pList2 := ProcessMessage(m2, peer, time.Now())
- //path2 := pList2[0].(*IPv4Path)
- //t2 = path2.timestamp
- adjRib.Update(pList2)
-
- inList := adjRib.PathList([]bgp.RouteFamily{bgp.RF_IPv4_UC}, false)
- assert.Equal(t, len(inList), 1)
- assert.Equal(t, inList[0].GetTimestamp(), t1)
-
- med2 := bgp.NewPathAttributeMultiExitDisc(1)
- pathAttributes2 := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med2,
- }
-
- m3 := bgp.NewBGPUpdateMessage(nil, pathAttributes2, nlri)
- pList3 := ProcessMessage(m3, peer, time.Now())
- t3 := pList3[0].GetTimestamp()
- adjRib.Update(pList3)
-
- inList = adjRib.PathList([]bgp.RouteFamily{bgp.RF_IPv4_UC}, false)
- assert.Equal(t, len(inList), 1)
- assert.Equal(t, inList[0].GetTimestamp(), t3)
-}
-
-func update_fromR1() *bgp.BGPMessage {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65000})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
-
- return bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
-}
-
-func update_fromR1_ipv6() *bgp.BGPMessage {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65000})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
-
- mp_nlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2001:123:123:1::")}
- mp_reach := bgp.NewPathAttributeMpReachNLRI("2001::192:168:50:1", mp_nlri)
- med := bgp.NewPathAttributeMultiExitDisc(0)
-
- pathAttributes := []bgp.PathAttributeInterface{
- mp_reach,
- origin,
- aspath,
- med,
- }
- return bgp.NewBGPUpdateMessage(nil, pathAttributes, nil)
-}
-
-func update_fromR2() *bgp.BGPMessage {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65100})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.100.1")
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "20.20.20.0")}
- return bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
-}
-
-func update_fromR2_ipv6() *bgp.BGPMessage {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspath := createAsPathAttribute([]uint32{65100})
- mp_reach := createMpReach("2001::192:168:100:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2002:223:123:1::")})
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{
- mp_reach,
- origin,
- aspath,
- med,
- }
- return bgp.NewBGPUpdateMessage(nil, pathAttributes, nil)
-}
-
-func createAsPathAttribute(ases []uint32) *bgp.PathAttributeAsPath {
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, ases)}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- return aspath
-}
-
-func createMpReach(nexthop string, prefix []bgp.AddrPrefixInterface) *bgp.PathAttributeMpReachNLRI {
- mp_reach := bgp.NewPathAttributeMpReachNLRI(nexthop, prefix)
- return mp_reach
-}
-
-func createMpUNReach(nlri string, len uint8) *bgp.PathAttributeMpUnreachNLRI {
- mp_nlri := []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(len, nlri)}
- mp_unreach := bgp.NewPathAttributeMpUnreachNLRI(mp_nlri)
- return mp_unreach
-}
-
-func update_fromR2viaR1() *bgp.BGPMessage {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65000, 65100})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "20.20.20.0")}
- return bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
-}
-
-func update_fromR2viaR1_ipv6() *bgp.BGPMessage {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspath := createAsPathAttribute([]uint32{65000, 65100})
- mp_reach := createMpReach("2001::192:168:50:1",
- []bgp.AddrPrefixInterface{bgp.NewIPv6AddrPrefix(64, "2002:223:123:1::")})
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{
- mp_reach,
- origin,
- aspath,
- med,
- }
- return bgp.NewBGPUpdateMessage(nil, pathAttributes, nil)
-
-}
diff --git a/table/table_test.go b/table/table_test.go
deleted file mode 100644
index 6228b995..00000000
--- a/table/table_test.go
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright (C) 2014 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 (
- "testing"
- "time"
-
- "github.com/osrg/gobgp/packet/bgp"
- "github.com/stretchr/testify/assert"
-)
-
-func TestTableDeleteDestByNlri(t *testing.T) {
- peerT := TableCreatePeer()
- pathT := TableCreatePath(peerT)
- ipv4t := NewTable(bgp.RF_IPv4_UC)
- for _, path := range pathT {
- dest := NewDestination(path.GetNlri(), 0)
- ipv4t.setDestination(dest)
- }
- gdest := ipv4t.GetDestination(pathT[0].GetNlri())
- rdest := ipv4t.deleteDestByNlri(pathT[0].GetNlri())
- assert.Equal(t, rdest, gdest)
-}
-
-func TestTableDeleteDest(t *testing.T) {
- peerT := TableCreatePeer()
- pathT := TableCreatePath(peerT)
- ipv4t := NewTable(bgp.RF_IPv4_UC)
- for _, path := range pathT {
- dest := NewDestination(path.GetNlri(), 0)
- ipv4t.setDestination(dest)
- }
- dest := NewDestination(pathT[0].GetNlri(), 0)
- ipv4t.setDestination(dest)
- ipv4t.deleteDest(dest)
- gdest := ipv4t.GetDestination(pathT[0].GetNlri())
- assert.Nil(t, gdest)
-}
-
-func TestTableGetRouteFamily(t *testing.T) {
- ipv4t := NewTable(bgp.RF_IPv4_UC)
- rf := ipv4t.GetRoutefamily()
- assert.Equal(t, rf, bgp.RF_IPv4_UC)
-}
-
-func TestTableSetDestinations(t *testing.T) {
- peerT := TableCreatePeer()
- pathT := TableCreatePath(peerT)
- ipv4t := NewTable(bgp.RF_IPv4_UC)
- destinations := make(map[string]*Destination)
- for _, path := range pathT {
- tableKey := ipv4t.tableKey(path.GetNlri())
- dest := NewDestination(path.GetNlri(), 0)
- destinations[tableKey] = dest
- }
- ipv4t.setDestinations(destinations)
- ds := ipv4t.GetDestinations()
- assert.Equal(t, ds, destinations)
-}
-func TestTableGetDestinations(t *testing.T) {
- peerT := DestCreatePeer()
- pathT := DestCreatePath(peerT)
- ipv4t := NewTable(bgp.RF_IPv4_UC)
- destinations := make(map[string]*Destination)
- for _, path := range pathT {
- tableKey := ipv4t.tableKey(path.GetNlri())
- dest := NewDestination(path.GetNlri(), 0)
- destinations[tableKey] = dest
- }
- ipv4t.setDestinations(destinations)
- ds := ipv4t.GetDestinations()
- assert.Equal(t, ds, destinations)
-}
-
-func TestTableKey(t *testing.T) {
- tb := NewTable(bgp.RF_IPv4_UC)
- n1, _ := bgp.NewPrefixFromRouteFamily(bgp.AFI_IP, bgp.SAFI_UNICAST, "0.0.0.0/0")
- d1 := NewDestination(n1, 0)
- n2, _ := bgp.NewPrefixFromRouteFamily(bgp.AFI_IP, bgp.SAFI_UNICAST, "0.0.0.0/1")
- d2 := NewDestination(n2, 0)
- assert.Equal(t, len(tb.tableKey(d1.GetNlri())), 5)
- tb.setDestination(d1)
- tb.setDestination(d2)
- assert.Equal(t, len(tb.GetDestinations()), 2)
-}
-
-func TableCreatePeer() []*PeerInfo {
- peerT1 := &PeerInfo{AS: 65000}
- peerT2 := &PeerInfo{AS: 65001}
- peerT3 := &PeerInfo{AS: 65002}
- peerT := []*PeerInfo{peerT1, peerT2, peerT3}
- return peerT
-}
-
-func TableCreatePath(peerT []*PeerInfo) []*Path {
- bgpMsgT1 := updateMsgT1()
- bgpMsgT2 := updateMsgT2()
- bgpMsgT3 := updateMsgT3()
- pathT := make([]*Path, 3)
- for i, msg := range []*bgp.BGPMessage{bgpMsgT1, bgpMsgT2, bgpMsgT3} {
- updateMsgT := msg.Body.(*bgp.BGPUpdate)
- nlriList := updateMsgT.NLRI
- pathAttributes := updateMsgT.PathAttributes
- nlri_info := nlriList[0]
- pathT[i] = NewPath(peerT[i], nlri_info, false, pathAttributes, time.Now(), false)
- }
- return pathT
-}
-
-func updateMsgT1() *bgp.BGPMessage {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65000})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.50.1")
- med := bgp.NewPathAttributeMultiExitDisc(0)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")}
- return bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
-}
-
-func updateMsgT2() *bgp.BGPMessage {
-
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65100})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.100.1")
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "20.20.20.0")}
- return bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
-}
-func updateMsgT3() *bgp.BGPMessage {
- origin := bgp.NewPathAttributeOrigin(0)
- aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65100})}
- aspath := bgp.NewPathAttributeAsPath(aspathParam)
- nexthop := bgp.NewPathAttributeNextHop("192.168.150.1")
- med := bgp.NewPathAttributeMultiExitDisc(100)
-
- pathAttributes := []bgp.PathAttributeInterface{
- origin,
- aspath,
- nexthop,
- med,
- }
-
- nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "30.30.30.0")}
- w1 := bgp.NewIPAddrPrefix(23, "40.40.40.0")
- withdrawnRoutes := []*bgp.IPAddrPrefix{w1}
- return bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri)
-}
diff --git a/table/vrf.go b/table/vrf.go
deleted file mode 100644
index f58bee2a..00000000
--- a/table/vrf.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2014-2016 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 (
- "github.com/osrg/gobgp/packet/bgp"
-)
-
-type Vrf struct {
- Name string
- Id uint32
- Rd bgp.RouteDistinguisherInterface
- ImportRt []bgp.ExtendedCommunityInterface
- ExportRt []bgp.ExtendedCommunityInterface
-}
-
-func (v *Vrf) Clone() *Vrf {
- f := func(rt []bgp.ExtendedCommunityInterface) []bgp.ExtendedCommunityInterface {
- l := make([]bgp.ExtendedCommunityInterface, 0, len(rt))
- return append(l, rt...)
- }
- return &Vrf{
- Name: v.Name,
- Id: v.Id,
- Rd: v.Rd,
- ImportRt: f(v.ImportRt),
- ExportRt: f(v.ExportRt),
- }
-}
-
-func isLastTargetUser(vrfs map[string]*Vrf, target bgp.ExtendedCommunityInterface) bool {
- for _, vrf := range vrfs {
- for _, rt := range vrf.ImportRt {
- if target.String() == rt.String() {
- return false
- }
- }
- }
- return true
-}