From a4d5d004cc3d97c90de0c2d91f2312525e055d68 Mon Sep 17 00:00:00 2001 From: Jordan Whited Date: Mon, 10 Aug 2020 09:43:54 -0700 Subject: best path selection - compare neigh addr --- internal/pkg/table/destination.go | 31 +++++++++++++++++++++++++++++++ internal/pkg/table/destination_test.go | 22 ++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/internal/pkg/table/destination.go b/internal/pkg/table/destination.go index 2880f662..0b438d78 100644 --- a/internal/pkg/table/destination.go +++ b/internal/pkg/table/destination.go @@ -50,6 +50,7 @@ const ( BPR_ROUTER_ID BPR_OLDER BPR_NON_LLGR_STALE + BPR_NEIGH_ADDR ) var BestPathReasonStringMap = map[BestPathReason]string{ @@ -68,6 +69,7 @@ var BestPathReasonStringMap = map[BestPathReason]string{ BPR_ROUTER_ID: "Router ID", BPR_OLDER: "Older", BPR_NON_LLGR_STALE: "no LLGR Stale", + BPR_NEIGH_ADDR: "Neighbor Address", } func (r *BestPathReason) String() string { @@ -480,6 +482,10 @@ func (dst *Destination) sort() BestPathReason { } reason = BPR_ROUTER_ID } + if better == nil { + better = compareByNeighborAddress(path1, path2) + reason = BPR_NEIGH_ADDR + } if better == nil { reason = BPR_UNKNOWN better = path1 @@ -918,6 +924,31 @@ func compareByRouterID(path1, path2 *Path) (*Path, error) { } } +func compareByNeighborAddress(path1, path2 *Path) *Path { + // Select the route received from the peer with the lowest peer address as + // per RFC 4271 9.1.2.2. g + log.WithFields(log.Fields{ + "Topic": "Table", + }).Debug("enter compareByNeighborAddress") + + p1 := path1.GetSource().Address + if p1 == nil { + return path1 + } + p2 := path2.GetSource().Address + if p2 == nil { + return path2 + } + + cmp := bytes.Compare(p1, p2) + if cmp < 0 { + return path1 + } else if cmp > 0 { + return path2 + } + return nil +} + func compareByAge(path1, path2 *Path) *Path { if !path1.IsIBGP() && !path2.IsIBGP() && !SelectionOptions.ExternalCompareRouterId { age1 := path1.GetTimestamp().UnixNano() diff --git a/internal/pkg/table/destination_test.go b/internal/pkg/table/destination_test.go index b1c1b2e8..3534cb6c 100644 --- a/internal/pkg/table/destination_test.go +++ b/internal/pkg/table/destination_test.go @@ -118,6 +118,28 @@ func TestCalculate2(t *testing.T) { assert.Equal(t, len(d.knownPathList), 3) } +func TestNeighAddrTieBreak(t *testing.T) { + nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0") + + peer0 := &PeerInfo{AS: 65001, LocalAS: 1, Address: net.IP{2, 2, 2, 2}, ID: net.IP{2, 2, 2, 2}} + + p0 := func() *Path { + aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001})}) + attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(0)} + return NewPath(peer0, nlri, false, attrs, time.Now(), false) + }() + + peer1 := &PeerInfo{AS: 65001, LocalAS: 1, Address: net.IP{3, 3, 3, 3}, ID: net.IP{2, 2, 2, 2}} // same ID as peer0, separate eBGP session + + p1 := func() *Path { + aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001})}) + attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(0)} + return NewPath(peer1, nlri, false, attrs, time.Now(), false) + }() + + assert.Equal(t, compareByNeighborAddress(p0, p1), p0) +} + func TestMedTieBreaker(t *testing.T) { nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0") -- cgit v1.2.3