From 60f8ce22620d914f6b798ad4fb85d3293ab8b42a Mon Sep 17 00:00:00 2001
From: Maximilian Wilhelm <max@sdn.clinic>
Date: Tue, 3 Jul 2018 16:36:15 +0200
Subject: [PATCH] Use BGP OriginatorID instead of RouterID for tie breaking, if
 present.

  According to RFC4456 Section 9 the OriginatorID has to be used instead
  of the Originator/RouterID when breaking ties, if an OriginatorID set
  by a route reflector is present.

  In addition a shorter ClusterList (none -> lenght 0) wins the best path
  election right after the aforementioned check.

Signed-off-by: Maximilian Wilhelm <max@sdn.clinic>
---
 route/bgp_path.go | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/route/bgp_path.go b/route/bgp_path.go
index ee9aca83..4b0b852c 100644
--- a/route/bgp_path.go
+++ b/route/bgp_path.go
@@ -27,6 +27,8 @@ type BGPPath struct {
 	Communities       []uint32
 	LargeCommunities  []types.LargeCommunity
 	UnknownAttributes []types.UnknownPathAttribute
+	OriginatorID      uint32
+	ClusterList       []uint32
 }
 
 // Length get's the length of serialized path
@@ -110,12 +112,33 @@ func (b *BGPPath) Compare(c *BGPPath) int8 {
 
 	// e) TODO: interiour cost (hello IS-IS and OSPF)
 
-	// f)
-	if c.BGPIdentifier < b.BGPIdentifier {
+	// f) + RFC4456 9. (Route Reflection)
+	bgpIdentifierC := c.BGPIdentifier
+	bgpIdentifierB := b.BGPIdentifier
+
+	// IF an OriginatorID (set by an RR) is present, use this instead of Originator
+	if c.OriginatorID != 0 {
+		bgpIdentifierC = c.OriginatorID
+	}
+
+	if b.OriginatorID != 0 {
+		bgpIdentifierB = b.OriginatorID
+	}
+
+	if bgpIdentifierC < bgpIdentifierB {
+		return 1
+	}
+
+	if bgpIdentifierC > bgpIdentifierB {
+		return -1
+	}
+
+	// Additionally check for the shorter ClusterList
+	if len(c.ClusterList) < len(b.ClusterList) {
 		return 1
 	}
 
-	if c.BGPIdentifier > b.BGPIdentifier {
+	if len(c.ClusterList) > len(b.ClusterList) {
 		return -1
 	}
 
-- 
GitLab