From 19b37b04d3d35d437209b193af641b3b9e283c3c Mon Sep 17 00:00:00 2001
From: Maximilian Wilhelm <max@sdn.clinic>
Date: Sun, 24 Jun 2018 00:56:11 +0200
Subject: [PATCH] Don't propagate path with detected AS loops to LocRIB or
 other clients.

Signed-off-by: Maximilian Wilhelm <max@sdn.clinic>
---
 routingtable/adjRIBIn/adj_rib_in.go   | 33 +++++++++++++++++++++++----
 routingtable/contributing_asn_list.go | 11 +++++++++
 2 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/routingtable/adjRIBIn/adj_rib_in.go b/routingtable/adjRIBIn/adj_rib_in.go
index 81416d9a..2d850024 100644
--- a/routingtable/adjRIBIn/adj_rib_in.go
+++ b/routingtable/adjRIBIn/adj_rib_in.go
@@ -3,6 +3,7 @@ package adjRIBIn
 import (
 	"sync"
 
+	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
 	"github.com/bio-routing/bio-rd/routingtable/filter"
 
 	"github.com/bio-routing/bio-rd/net"
@@ -14,16 +15,18 @@ import (
 // AdjRIBIn represents an Adjacency RIB In as described in RFC4271
 type AdjRIBIn struct {
 	routingtable.ClientManager
-	rt           *routingtable.RoutingTable
-	mu           sync.RWMutex
-	exportFilter *filter.Filter
+	rt               *routingtable.RoutingTable
+	mu               sync.RWMutex
+	exportFilter     *filter.Filter
+	contributingASNs *routingtable.ContributingASNs
 }
 
 // New creates a new Adjacency RIB In
 func New(exportFilter *filter.Filter, contributingASNs *routingtable.ContributingASNs) *AdjRIBIn {
 	a := &AdjRIBIn{
-		rt:           routingtable.NewRoutingTable(),
-		exportFilter: exportFilter,
+		rt:               routingtable.NewRoutingTable(),
+		exportFilter:     exportFilter,
+		contributingASNs: contributingASNs,
 	}
 	a.ClientManager = routingtable.NewClientManager(a)
 	return a
@@ -65,12 +68,32 @@ func (a *AdjRIBIn) AddPath(pfx net.Prefix, p *route.Path) error {
 		return nil
 	}
 
+	// Bail out - for all clients for now - if any of our ASNs is within the path
+	if a.ourASNsInPath(p) {
+		return nil
+	}
+
 	for _, client := range a.ClientManager.Clients() {
 		client.AddPath(pfx, p)
 	}
 	return nil
 }
 
+func (a *AdjRIBIn) ourASNsInPath(p *route.Path) bool {
+	// Don't accept path via iBGP which contain our ASN
+	ASPathAttr, _ := packet.ParseASPathStr(p.BGPPath.ASPath)
+
+	for _, pathSegment := range ASPathAttr.Value.(packet.ASPath) {
+		for _, asn := range pathSegment.ASNs {
+			if a.contributingASNs.IsContributingASN(asn) {
+				return true
+			}
+		}
+	}
+
+	return false
+}
+
 // RemovePath removes the path for prefix `pfx`
 func (a *AdjRIBIn) RemovePath(pfx net.Prefix, p *route.Path) bool {
 	a.mu.Lock()
diff --git a/routingtable/contributing_asn_list.go b/routingtable/contributing_asn_list.go
index 0b0efca2..be981ce2 100644
--- a/routingtable/contributing_asn_list.go
+++ b/routingtable/contributing_asn_list.go
@@ -62,3 +62,14 @@ func (c *ContributingASNs) Remove(asn uint32) {
 		}
 	}
 }
+
+// IsContributingASN checks if  a given ASN is part of the contributing ASNs
+func (c *ContributingASNs) IsContributingASN(asn uint32) bool {
+	for _, cASN := range c.contributingASNs {
+		if asn == cASN.asn {
+			return true
+		}
+	}
+
+	return false
+}
-- 
GitLab