diff --git a/protocols/bgp/server/fsm_address_family.go b/protocols/bgp/server/fsm_address_family.go index 772a2dbf436cf1256ce965f16f0cb7ac5a2e1647..0b241ecca48b4a6169a918843eedc64cf042e5e3 100644 --- a/protocols/bgp/server/fsm_address_family.go +++ b/protocols/bgp/server/fsm_address_family.go @@ -29,9 +29,8 @@ type fsmAddressFamily struct { updateSender *UpdateSender - addPathSend routingtable.ClientOptions - addPathTXConfigured bool - addPathTX bool + addPathTX routingtable.ClientOptions + addPathRX bool multiProtocol bool @@ -40,38 +39,30 @@ type fsmAddressFamily struct { func newFSMAddressFamily(afi uint16, safi uint8, family *peerAddressFamily, fsm *FSM) *fsmAddressFamily { return &fsmAddressFamily{ - afi: afi, - safi: safi, - fsm: fsm, - rib: family.rib, - importFilter: family.importFilter, - exportFilter: family.exportFilter, - addPathTXConfigured: family.addPathReceive, // at this point we switch from peers view to our view - addPathSend: family.addPathSend, + afi: afi, + safi: safi, + fsm: fsm, + rib: family.rib, + importFilter: family.importFilter, + exportFilter: family.exportFilter, } } func (f *fsmAddressFamily) init(n *routingtable.Neighbor) { contributingASNs := f.rib.GetContributingASNs() - f.adjRIBIn = adjRIBIn.New(f.importFilter, contributingASNs, f.fsm.peer.routerID, f.fsm.peer.clusterID) + f.adjRIBIn = adjRIBIn.New(f.importFilter, contributingASNs, f.fsm.peer.routerID, f.fsm.peer.clusterID, f.addPathRX) contributingASNs.Add(f.fsm.peer.localASN) f.adjRIBIn.Register(f.rib) - f.adjRIBOut = adjRIBOut.New(n, f.exportFilter, f.addPathTX) + f.adjRIBOut = adjRIBOut.New(n, f.exportFilter, !f.addPathTX.BestOnly) f.updateSender = newUpdateSender(f.fsm, f.afi, f.safi) f.updateSender.Start(time.Millisecond * 5) f.adjRIBOut.Register(f.updateSender) - clientOptions := routingtable.ClientOptions{ - BestOnly: true, - } - if f.addPathTX { - clientOptions = f.addPathSend - } - f.rib.RegisterWithOptions(f.adjRIBOut, clientOptions) + f.rib.RegisterWithOptions(f.adjRIBOut, f.addPathTX) } func (f *fsmAddressFamily) dispose() { diff --git a/protocols/bgp/server/fsm_open_sent.go b/protocols/bgp/server/fsm_open_sent.go index a276ef47ee0c1b57422df07be7b96a74c4a9c7d1..a3aac48a22add9132441a589994cca7752a689d7 100644 --- a/protocols/bgp/server/fsm_open_sent.go +++ b/protocols/bgp/server/fsm_open_sent.go @@ -202,21 +202,24 @@ func (s *openSentState) processAddPathCapability(addPathCap packet.AddPathCapabi return } + peerAddressFamily := s.fsm.peer.addressFamily(addPathCap.AFI, addPathCap.SAFI) + switch addPathCap.SendReceive { case packet.AddPathReceive: - if !f.addPathSend.BestOnly { - f.addPathTX = true + if !peerAddressFamily.addPathSend.BestOnly { + f.addPathTX = peerAddressFamily.addPathSend } case packet.AddPathSend: - if f.addPathTXConfigured { - f.addPathTX = true + if peerAddressFamily.addPathReceive { + f.addPathRX = true } case packet.AddPathSendReceive: - if !f.addPathSend.BestOnly { - f.addPathTX = true + if !peerAddressFamily.addPathSend.BestOnly { + f.addPathTX = peerAddressFamily.addPathSend } - if f.addPathTXConfigured { - f.addPathTX = true + + if peerAddressFamily.addPathReceive { + f.addPathRX = true } } } diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go index d57b22d731d1e5bc394915e2ff19e6097e205722..9a5b128aacc89a7fa996b75b7e175e8a97dd4d2d 100644 --- a/protocols/bgp/server/peer.go +++ b/protocols/bgp/server/peer.go @@ -53,6 +53,21 @@ type peerAddressFamily struct { addPathReceive bool } +func (p *peer) addressFamily(afi uint16, safi uint8) *peerAddressFamily { + if safi != packet.UnicastSAFI { + return nil + } + + switch afi { + case packet.IPv4AFI: + return p.ipv4 + case packet.IPv6AFI: + return p.ipv6 + default: + return nil + } +} + func (p *peer) snapshot() PeerInfo { p.fsmsMu.Lock() defer p.fsmsMu.Unlock() diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go index 17b021a55504af3e6cba17285da7a33ba9d0a360..aaf1b744008c1d3df14a10ff2bc57573a636aa9d 100644 --- a/protocols/bgp/server/update_sender.go +++ b/protocols/bgp/server/update_sender.go @@ -44,7 +44,7 @@ func newUpdateSender(fsm *FSM, afi uint16, safi uint8) *UpdateSender { toSend: make(map[string]*pathPfxs), options: &packet.EncodeOptions{ Use32BitASN: fsm.supports4OctetASN, - UseAddPath: f.addPathTX, + UseAddPath: !f.addPathTX.BestOnly, }, } } diff --git a/protocols/bgp/server/update_sender_test.go b/protocols/bgp/server/update_sender_test.go index 4b6ae30722018a287f86aaa046d30252008bd944..516a2d59f181e9831095b8cdcc36c588c64cdc28 100644 --- a/protocols/bgp/server/update_sender_test.go +++ b/protocols/bgp/server/update_sender_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/bio-routing/bio-rd/protocols/bgp/packet" + "github.com/bio-routing/bio-rd/routingtable" "github.com/stretchr/testify/assert" @@ -24,12 +25,13 @@ func TestSender(t *testing.T) { paths []pathPfxs generateNLRIs uint64 expectedUpdates [][]byte - addPath bool + addPath routingtable.ClientOptions afi uint16 }{ { - name: "Two paths with 3 NLRIs each", - afi: packet.IPv4AFI, + name: "Two paths with 3 NLRIs each", + afi: packet.IPv4AFI, + addPath: routingtable.ClientOptions{BestOnly: true}, paths: []pathPfxs{ { path: &route.Path{ @@ -92,7 +94,7 @@ func TestSender(t *testing.T) { { name: "Two paths with 3 NLRIs each with BGP Add Path", afi: packet.IPv4AFI, - addPath: true, + addPath: routingtable.ClientOptions{MaxPaths: 10}, paths: []pathPfxs{ { path: &route.Path{ @@ -169,8 +171,9 @@ func TestSender(t *testing.T) { }, }, { - name: "Overflow. Too many NLRIs.", - afi: packet.IPv4AFI, + name: "Overflow. Too many NLRIs.", + afi: packet.IPv4AFI, + addPath: routingtable.ClientOptions{BestOnly: true}, paths: []pathPfxs{ { path: &route.Path{ @@ -337,8 +340,9 @@ func TestSender(t *testing.T) { }, }, { - name: "Overflow with IPv6. Too many NLRIs.", - afi: packet.IPv6AFI, + name: "Overflow with IPv6. Too many NLRIs.", + afi: packet.IPv6AFI, + addPath: routingtable.ClientOptions{BestOnly: true}, paths: []pathPfxs{ { path: &route.Path{ @@ -946,7 +950,7 @@ func TestSender(t *testing.T) { func TestWithdrawPrefix(t *testing.T) { testcases := []struct { name string - addPathTX bool + addPathTX routingtable.ClientOptions afi uint16 multiProtocol bool prefix bnet.Prefix @@ -958,7 +962,7 @@ func TestWithdrawPrefix(t *testing.T) { name: "Non bgp withdraw with ADD-PATH", afi: packet.IPv4AFI, multiProtocol: false, - addPathTX: true, + addPathTX: routingtable.ClientOptions{MaxPaths: 10}, prefix: bnet.NewPfx(bnet.IPv4(1413010532), 24), path: &route.Path{ Type: route.StaticPathType, @@ -970,7 +974,7 @@ func TestWithdrawPrefix(t *testing.T) { name: "Nil BGPPathType with ADD-PATH", afi: packet.IPv4AFI, multiProtocol: false, - addPathTX: true, + addPathTX: routingtable.ClientOptions{MaxPaths: 10}, prefix: bnet.NewPfx(bnet.IPv4(1413010532), 24), path: &route.Path{ Type: route.BGPPathType, @@ -982,7 +986,7 @@ func TestWithdrawPrefix(t *testing.T) { name: "Normal withdraw with ADD-PATH", afi: packet.IPv4AFI, multiProtocol: false, - addPathTX: true, + addPathTX: routingtable.ClientOptions{MaxPaths: 10}, prefix: bnet.NewPfx(bnet.IPv4(1413010532), 24), path: &route.Path{ Type: route.BGPPathType, @@ -1006,7 +1010,7 @@ func TestWithdrawPrefix(t *testing.T) { name: "Normal withdraw without ADD-PATH", afi: packet.IPv4AFI, multiProtocol: false, - addPathTX: false, + addPathTX: routingtable.ClientOptions{BestOnly: true}, prefix: bnet.NewPfx(bnet.IPv4(1413010532), 24), path: &route.Path{ Type: route.BGPPathType, @@ -1029,7 +1033,7 @@ func TestWithdrawPrefix(t *testing.T) { name: "IPv6 MP_UNREACH_NLRI", afi: packet.IPv6AFI, multiProtocol: true, - addPathTX: false, + addPathTX: routingtable.ClientOptions{BestOnly: true}, prefix: bnet.NewPfx(bnet.IPv6FromBlocks(0x2804, 0x148c, 0, 0, 0, 0, 0, 0), 32), path: &route.Path{ Type: route.BGPPathType, @@ -1053,7 +1057,7 @@ func TestWithdrawPrefix(t *testing.T) { name: "IPv6 MP_UNREACH_NLRI with ADD-PATH", afi: packet.IPv6AFI, multiProtocol: true, - addPathTX: true, + addPathTX: routingtable.ClientOptions{MaxPaths: 10}, prefix: bnet.NewPfx(bnet.IPv6FromBlocks(0x2804, 0x148c, 0, 0, 0, 0, 0, 0), 32), path: &route.Path{ Type: route.BGPPathType, @@ -1080,7 +1084,7 @@ func TestWithdrawPrefix(t *testing.T) { name: "IPv6 MP_UNREACH_NLRI without multi protocol beeing negotiated", afi: packet.IPv6AFI, multiProtocol: false, - addPathTX: false, + addPathTX: routingtable.ClientOptions{BestOnly: true}, prefix: bnet.NewPfx(bnet.IPv6FromBlocks(0x2804, 0x148c, 0, 0, 0, 0, 0, 0), 32), path: &route.Path{ Type: route.BGPPathType, @@ -1108,7 +1112,7 @@ func TestWithdrawPrefix(t *testing.T) { safi: packet.UnicastSAFI, }, options: &packet.EncodeOptions{ - UseAddPath: tc.addPathTX, + UseAddPath: !tc.addPathTX.BestOnly, }, } diff --git a/route/bgp_path.go b/route/bgp_path.go index e2fe080c30885b439c72e7528ce86c076a0a3f72..78c6d2a327bebd62eb5ed1cc4145b56ad0d50398 100644 --- a/route/bgp_path.go +++ b/route/bgp_path.go @@ -73,8 +73,17 @@ func (b *BGPPath) ECMP(c *BGPPath) bool { return b.LocalPref == c.LocalPref && b.ASPathLen == c.ASPathLen && b.MED == c.MED && b.Origin == c.Origin } -// Compare returns negative if b < c, 0 if paths are equal, positive if b > c -func (b *BGPPath) Compare(c *BGPPath) int8 { +// Equal checks if paths are equal +func (b *BGPPath) Equal(c *BGPPath) bool { + if b.PathIdentifier != c.PathIdentifier { + return false + } + + return b.Select(c) == 0 +} + +// Select returns negative if b < c, 0 if paths are equal, positive if b > c +func (b *BGPPath) Select(c *BGPPath) int8 { if c.LocalPref < b.LocalPref { return 1 } diff --git a/route/path.go b/route/path.go index ef4da4068f7bd81b4051e5d91d93d137d8832af1..0f7d8372a9f04e93eed1ec24b9f14407f36fb6fd 100644 --- a/route/path.go +++ b/route/path.go @@ -10,8 +10,8 @@ type Path struct { BGPPath *BGPPath } -// Compare returns negative if p < q, 0 if paths are equal, positive if p > q -func (p *Path) Compare(q *Path) int8 { +// Select returns negative if p < q, 0 if paths are equal, positive if p > q +func (p *Path) Select(q *Path) int8 { switch { case p == nil && q == nil: return 0 @@ -32,9 +32,9 @@ func (p *Path) Compare(q *Path) int8 { switch p.Type { case BGPPathType: - return p.BGPPath.Compare(q.BGPPath) + return p.BGPPath.Select(q.BGPPath) case StaticPathType: - return p.StaticPath.Compare(q.StaticPath) + return p.StaticPath.Select(q.StaticPath) } panic("Unknown path type") @@ -55,7 +55,19 @@ func (p *Path) Equal(q *Path) bool { if p == nil || q == nil { return false } - return p.Compare(q) == 0 + + if p.Type != q.Type { + return false + } + + switch p.Type { + case BGPPathType: + return p.BGPPath.Equal(q.BGPPath) + case StaticPathType: + return p.StaticPath.Equal(q.StaticPath) + } + + return p.Select(q) == 0 } // PathsDiff gets the list of elements contained by a but not b diff --git a/route/route.go b/route/route.go index 51d00db5c860ba6aff88023da0449f17ff2a8cf5..f263f70bcd7573b381299759d4ca24ba5440f5fe 100644 --- a/route/route.go +++ b/route/route.go @@ -185,7 +185,7 @@ func (r *Route) PathSelection() { defer r.mu.Unlock() sort.Slice(r.paths, func(i, j int) bool { - return r.paths[i].Compare(r.paths[j]) == -1 + return r.paths[i].Select(r.paths[j]) == -1 }) r.updateEqualPathCount() diff --git a/route/static.go b/route/static.go index af2990f25ba164346587bf1b3ebb0dae2011ffea..df282d2217eca7a4457a65f995cc2427cd9789e9 100644 --- a/route/static.go +++ b/route/static.go @@ -16,11 +16,16 @@ func (r *Route) staticPathSelection() { return } -// Compare returns negative if s < t, 0 if paths are equal, positive if s > t -func (s *StaticPath) Compare(t *StaticPath) int8 { +// Select returns negative if s < t, 0 if paths are equal, positive if s > t +func (s *StaticPath) Select(t *StaticPath) int8 { return 0 } +// Equal returns true if s and t are euqal +func (s *StaticPath) Equal(t *StaticPath) bool { + return s.NextHop == t.NextHop +} + // ECMP determines if path s and t are equal in terms of ECMP func (s *StaticPath) ECMP(t *StaticPath) bool { return true diff --git a/routingtable/adjRIBIn/adj_rib_in.go b/routingtable/adjRIBIn/adj_rib_in.go index 319e28690170ae37df83ec2c480cea752b6ce7f1..631f1d197cabc926056f186e21e1b6cd5d719afd 100644 --- a/routingtable/adjRIBIn/adj_rib_in.go +++ b/routingtable/adjRIBIn/adj_rib_in.go @@ -20,16 +20,18 @@ type AdjRIBIn struct { contributingASNs *routingtable.ContributingASNs routerID uint32 clusterID uint32 + addPathRX bool } // New creates a new Adjacency RIB In -func New(exportFilter *filter.Filter, contributingASNs *routingtable.ContributingASNs, routerID uint32, clusterID uint32) *AdjRIBIn { +func New(exportFilter *filter.Filter, contributingASNs *routingtable.ContributingASNs, routerID uint32, clusterID uint32, addPathRX bool) *AdjRIBIn { a := &AdjRIBIn{ rt: routingtable.NewRoutingTable(), exportFilter: exportFilter, contributingASNs: contributingASNs, routerID: routerID, clusterID: clusterID, + addPathRX: addPathRX, } a.ClientManager = routingtable.NewClientManager(a) return a @@ -82,8 +84,12 @@ func (a *AdjRIBIn) AddPath(pfx net.Prefix, p *route.Path) error { } } - oldPaths := a.rt.ReplacePath(pfx, p) - a.removePathsFromClients(pfx, oldPaths) + if a.addPathRX { + a.rt.AddPath(pfx, p) + } else { + oldPaths := a.rt.ReplacePath(pfx, p) + a.removePathsFromClients(pfx, oldPaths) + } p, reject := a.exportFilter.ProcessTerms(pfx, p) if reject { @@ -123,12 +129,20 @@ func (a *AdjRIBIn) RemovePath(pfx net.Prefix, p *route.Path) bool { return false } + removed := make([]*route.Path, 0) oldPaths := r.Paths() for _, path := range oldPaths { + if a.addPathRX { + if path.BGPPath.PathIdentifier != p.BGPPath.PathIdentifier { + continue + } + } + a.rt.RemovePath(pfx, path) + removed = append(removed, path) } - a.removePathsFromClients(pfx, oldPaths) + a.removePathsFromClients(pfx, removed) return true } diff --git a/routingtable/adjRIBIn/adj_rib_in_test.go b/routingtable/adjRIBIn/adj_rib_in_test.go index deec00104931a80f128be6782df70e35407775ae..76bbc90d23b8d9974819648c3921cb2ee99fdee2 100644 --- a/routingtable/adjRIBIn/adj_rib_in_test.go +++ b/routingtable/adjRIBIn/adj_rib_in_test.go @@ -17,6 +17,7 @@ func TestAddPath(t *testing.T) { tests := []struct { name string + addPath bool routes []*route.Route removePfx net.Prefix removePath *route.Path @@ -104,10 +105,46 @@ func TestAddPath(t *testing.T) { }, expected: []*route.Route{}, }, + { + name: "Add route (with BGP add path)", + addPath: true, + routes: []*route.Route{ + route.NewRoute(net.NewPfx(net.IPv4FromOctets(10, 0, 0, 0), 8), &route.Path{ + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + LocalPref: 100, + }, + }), + route.NewRoute(net.NewPfx(net.IPv4FromOctets(10, 0, 0, 0), 8), &route.Path{ + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + LocalPref: 200, + }, + }), + }, + removePfx: net.Prefix{}, + removePath: nil, + expected: []*route.Route{ + route.NewRouteAddPath(net.NewPfx(net.IPv4FromOctets(10, 0, 0, 0), 8), []*route.Path{ + { + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + LocalPref: 100, + }, + }, + { + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + LocalPref: 200, + }, + }, + }), + }, + }, } for _, test := range tests { - adjRIBIn := New(filter.NewAcceptAllFilter(), routingtable.NewContributingASNs(), routerID, clusterID) + adjRIBIn := New(filter.NewAcceptAllFilter(), routingtable.NewContributingASNs(), routerID, clusterID, test.addPath) mc := routingtable.NewRTMockClient() adjRIBIn.ClientManager.Register(mc) @@ -130,12 +167,61 @@ func TestAddPath(t *testing.T) { func TestRemovePath(t *testing.T) { tests := []struct { name string + addPath bool routes []*route.Route removePfx net.Prefix removePath *route.Path expected []*route.Route wantPropagation bool }{ + { + name: "Remove an a path from existing route", + addPath: true, + routes: []*route.Route{ + route.NewRoute(net.NewPfx(net.IPv4FromOctets(10, 0, 0, 0), 8), &route.Path{ + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + PathIdentifier: 100, + }, + }), + route.NewRoute(net.NewPfx(net.IPv4FromOctets(10, 0, 0, 0), 8), &route.Path{ + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + PathIdentifier: 200, + }, + }), + route.NewRoute(net.NewPfx(net.IPv4FromOctets(10, 0, 0, 0), 8), &route.Path{ + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + PathIdentifier: 300, + }, + }), + }, + removePfx: net.NewPfx(net.IPv4FromOctets(10, 0, 0, 0), 8), + removePath: &route.Path{ + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + PathIdentifier: 200, + }, + }, + expected: []*route.Route{ + route.NewRouteAddPath(net.NewPfx(net.IPv4FromOctets(10, 0, 0, 0), 8), []*route.Path{ + { + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + PathIdentifier: 100, + }, + }, + { + Type: route.BGPPathType, + BGPPath: &route.BGPPath{ + PathIdentifier: 300, + }, + }, + }), + }, + wantPropagation: true, + }, { name: "Remove an existing route", routes: []*route.Route{ @@ -201,7 +287,7 @@ func TestRemovePath(t *testing.T) { } for _, test := range tests { - adjRIBIn := New(filter.NewAcceptAllFilter(), routingtable.NewContributingASNs(), 1, 2) + adjRIBIn := New(filter.NewAcceptAllFilter(), routingtable.NewContributingASNs(), 1, 2, test.addPath) for _, route := range test.routes { adjRIBIn.AddPath(route.Prefix(), route.Paths()[0]) } diff --git a/routingtable/adjRIBOut/adj_rib_out.go b/routingtable/adjRIBOut/adj_rib_out.go index a93a5cfe44ab570ce41873b7b6ad416dbd9fb8c3..289dc7da1202cafd259aa93aa24f69b8f0e784fc 100644 --- a/routingtable/adjRIBOut/adj_rib_out.go +++ b/routingtable/adjRIBOut/adj_rib_out.go @@ -138,21 +138,30 @@ func (a *AdjRIBOut) RemovePath(pfx bnet.Prefix, p *route.Path) bool { return false } - a.rt.RemovePath(pfx, p) - - // If the neighbar has AddPath capabilities, try to find the PathID + sentPath := p if a.addPathTX { - pathID, err := a.pathIDManager.releasePath(p) - if err != nil { - log.Warningf("Unable to release path for prefix %s: %v", pfx.String(), err) - return true + for _, sentPath := range r.Paths() { + if sentPath.Select(p) != 0 { + continue + } + + a.rt.RemovePath(pfx, sentPath) + + _, err := a.pathIDManager.releasePath(p) + if err != nil { + log.Warningf("Unable to release path for prefix %s: %v", pfx.String(), err) + return true + } } - p = p.Copy() - p.BGPPath.PathIdentifier = pathID + if sentPath == p { + return false + } + } else { + a.rt.RemovePath(pfx, p) } - a.removePathFromClients(pfx, p) + a.removePathFromClients(pfx, sentPath) return true } diff --git a/routingtable/adjRIBOut/adj_rib_out_test.go b/routingtable/adjRIBOut/adj_rib_out_test.go index 70004a32edac2f396d084b722dfa165b7bf56b9d..10806b3a2bcc0a3aff2b889af75988da7f48918b 100644 --- a/routingtable/adjRIBOut/adj_rib_out_test.go +++ b/routingtable/adjRIBOut/adj_rib_out_test.go @@ -332,7 +332,7 @@ func TestBestPathOnlyIBGP(t *testing.T) { adjRIBOut := New(neighborBestOnlyEBGP, filter.NewAcceptAllFilter(), false) - tests := []struct { + testSteps := []struct { name string routesAdd []*route.Route routesRemove []*route.Route @@ -511,7 +511,7 @@ func TestBestPathOnlyIBGP(t *testing.T) { }, } - for i, test := range tests { + for i, test := range testSteps { fmt.Printf("Running iBGP best only test #%d: %s\n", i+1, test.name) for _, route := range test.routesAdd { adjRIBOut.AddPath(route.Prefix(), route.Paths()[0]) @@ -1438,11 +1438,14 @@ func TestAddPathIBGP(t *testing.T) { adjRIBOut.RemovePath(route.Prefix(), route.Paths()[0]) } - assert.Equal(t, test.expected, adjRIBOut.rt.Dump()) + if !assert.Equalf(t, test.expected, adjRIBOut.rt.Dump(), "Test %q", test.name) { + return + } actualCount := adjRIBOut.RouteCount() if test.expectedCount != actualCount { t.Errorf("Expected route count %d differs from actual route count %d!\n", test.expectedCount, actualCount) + return } } } diff --git a/routingtable/locRIB/loc_rib.go b/routingtable/locRIB/loc_rib.go index 037565a86e32b77f4344d40724b0781094234f22..d9ad2b46f29ee95d8a0d6b42ff513bd7172e067f 100644 --- a/routingtable/locRIB/loc_rib.go +++ b/routingtable/locRIB/loc_rib.go @@ -168,7 +168,7 @@ func (a *LocRIB) ContainsPfxPath(pfx net.Prefix, p *route.Path) bool { } for _, path := range r.Paths() { - if path.Compare(p) == 0 { + if path.Equal(p) { return true } }