diff --git a/protocols/bgp/server/fsm.go b/protocols/bgp/server/fsm.go
index 33e000d1c6010a2e3b976b13bec591a7e0e67545..0c5221391c80e1dbd7bf1262d2506192eba80924 100644
--- a/protocols/bgp/server/fsm.go
+++ b/protocols/bgp/server/fsm.go
@@ -8,6 +8,7 @@ import (
 
 	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
 	"github.com/bio-routing/bio-rd/routingtable"
+	"github.com/bio-routing/bio-rd/routingtable/locRIB"
 	log "github.com/sirupsen/logrus"
 )
 
@@ -61,7 +62,7 @@ type FSM struct {
 	ribsInitialized bool
 	adjRIBIn        routingtable.RouteTableClient
 	adjRIBOut       routingtable.RouteTableClient
-	rib             routingtable.RouteTableClient
+	rib             *locRIB.LocRIB
 	updateSender    routingtable.RouteTableClient
 
 	neighborID uint32
diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go
index 80ff7fa7990493186924f8c35f1a90deb0c93e5b..58facab0cd4ad487245cfe431a73478d3ca455a8 100644
--- a/protocols/bgp/server/fsm_established.go
+++ b/protocols/bgp/server/fsm_established.go
@@ -55,7 +55,10 @@ func (s establishedState) run() (state, string) {
 }
 
 func (s *establishedState) init() error {
-	s.fsm.adjRIBIn = adjRIBIn.New(s.fsm.peer.importFilter)
+	contributingASNs := s.fsm.rib.GetContributingASNs()
+
+	s.fsm.adjRIBIn = adjRIBIn.New(s.fsm.peer.importFilter, contributingASNs)
+	contributingASNs.Add(s.fsm.peer.localASN)
 	s.fsm.adjRIBIn.Register(s.fsm.rib)
 
 	host, _, err := net.SplitHostPort(s.fsm.con.LocalAddr().String())
@@ -96,6 +99,7 @@ func (s *establishedState) init() error {
 }
 
 func (s *establishedState) uninit() {
+	s.fsm.rib.GetContributingASNs().Remove(s.fsm.peer.localASN)
 	s.fsm.adjRIBIn.Unregister(s.fsm.rib)
 	s.fsm.rib.Unregister(s.fsm.adjRIBOut)
 	s.fsm.adjRIBOut.Unregister(s.fsm.updateSender)
diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go
index bad268285a156e5d32576af75521f42a7436a603..3e5e6aeea408d1be12c4fd1ca38b6e62ba2af3b4 100644
--- a/protocols/bgp/server/peer.go
+++ b/protocols/bgp/server/peer.go
@@ -5,6 +5,8 @@ import (
 	"sync"
 	"time"
 
+	"github.com/bio-routing/bio-rd/routingtable/locRIB"
+
 	"github.com/bio-routing/bio-rd/config"
 	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
 	"github.com/bio-routing/bio-rd/routingtable"
@@ -27,7 +29,7 @@ type peer struct {
 	fsms   []*FSM
 	fsmsMu sync.Mutex
 
-	rib               routingtable.RouteTableClient
+	rib               *locRIB.LocRIB
 	routerID          uint32
 	addPathSend       routingtable.ClientOptions
 	addPathRecv       bool
@@ -100,7 +102,7 @@ func isEstablishedState(s state) bool {
 
 // NewPeer creates a new peer with the given config. If an connection is established, the adjRIBIN of the peer is connected
 // to the given rib. To actually connect the peer, call Start() on the returned peer.
-func newPeer(c config.Peer, rib routingtable.RouteTableClient, server *bgpServer) (*peer, error) {
+func newPeer(c config.Peer, rib *locRIB.LocRIB, server *bgpServer) (*peer, error) {
 	if c.LocalAS == 0 {
 		c.LocalAS = server.localASN
 	}
diff --git a/protocols/bgp/server/server.go b/protocols/bgp/server/server.go
index 61c79de10315e5efa65c27e7da820b3a39aee4df..f0354f7ed1587ffd2ec84132ec50e117edfb72bb 100644
--- a/protocols/bgp/server/server.go
+++ b/protocols/bgp/server/server.go
@@ -7,9 +7,10 @@ import (
 	"strings"
 	"sync"
 
+	"github.com/bio-routing/bio-rd/routingtable/locRIB"
+
 	"github.com/bio-routing/bio-rd/config"
 	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
-	"github.com/bio-routing/bio-rd/routingtable"
 	log "github.com/sirupsen/logrus"
 )
 
@@ -29,7 +30,7 @@ type bgpServer struct {
 type BGPServer interface {
 	RouterID() uint32
 	Start(*config.Global) error
-	AddPeer(config.Peer, routingtable.RouteTableClient) error
+	AddPeer(config.Peer, *locRIB.LocRIB) error
 	GetPeerInfoAll() map[string]PeerInfo
 }
 
@@ -113,7 +114,7 @@ func (b *bgpServer) incomingConnectionWorker() {
 	}
 }
 
-func (b *bgpServer) AddPeer(c config.Peer, rib routingtable.RouteTableClient) error {
+func (b *bgpServer) AddPeer(c config.Peer, rib *locRIB.LocRIB) error {
 	if c.LocalAS > uint16max || c.PeerAS > uint16max {
 		return fmt.Errorf("32bit ASNs are not supported yet")
 	}
diff --git a/routingtable/adjRIBIn/adj_rib_in.go b/routingtable/adjRIBIn/adj_rib_in.go
index ca9d0bb07570811beec3ffa3eb99ec12423f6041..81416d9a488ac25711946d8b64f8bfe316a31a5a 100644
--- a/routingtable/adjRIBIn/adj_rib_in.go
+++ b/routingtable/adjRIBIn/adj_rib_in.go
@@ -20,7 +20,7 @@ type AdjRIBIn struct {
 }
 
 // New creates a new Adjacency RIB In
-func New(exportFilter *filter.Filter) *AdjRIBIn {
+func New(exportFilter *filter.Filter, contributingASNs *routingtable.ContributingASNs) *AdjRIBIn {
 	a := &AdjRIBIn{
 		rt:           routingtable.NewRoutingTable(),
 		exportFilter: exportFilter,
diff --git a/routingtable/contributing_asn_list.go b/routingtable/contributing_asn_list.go
new file mode 100644
index 0000000000000000000000000000000000000000..0b0efca268d477d59728bbf44151f75d733845f3
--- /dev/null
+++ b/routingtable/contributing_asn_list.go
@@ -0,0 +1,64 @@
+package routingtable
+
+import (
+	"sync"
+)
+
+type contributingASN struct {
+	asn   uint32
+	count uint32
+}
+
+// ContributingASNs contains a list of contributing ASN to a LocRIB to check ASPaths for possible routing loops.
+type ContributingASNs struct {
+	contributingASNs []contributingASN
+	mu               sync.RWMutex
+}
+
+// NewContributingASNs creates a list of contributing ASNs to a LocRIB for routing loop prevention.
+func NewContributingASNs() *ContributingASNs {
+	c := &ContributingASNs{
+		contributingASNs: []contributingASN{},
+	}
+
+	return c
+}
+
+// Add a new ASN to the list of contributing ASNs or add the ref count of an existing one.
+func (c *ContributingASNs) Add(asn uint32) {
+	c.mu.RLock()
+	defer c.mu.RUnlock()
+
+	for _, cASN := range c.contributingASNs {
+		if cASN.asn == asn {
+			cASN.count++
+			return
+		}
+	}
+
+	c.contributingASNs = append(c.contributingASNs, contributingASN{
+		asn:   asn,
+		count: 1,
+	})
+}
+
+// Remove a ASN to the list of contributing ASNs or decrement the ref count of an existing one.
+func (c *ContributingASNs) Remove(asn uint32) {
+	c.mu.RLock()
+	defer c.mu.RUnlock()
+
+	asnList := c.contributingASNs
+
+	for i, cASN := range asnList {
+		if cASN.asn == asn {
+			cASN.count--
+
+			if cASN.count == 0 {
+				copy(asnList[i:], asnList[i+1:])
+				asnList = asnList[:len(asnList)]
+				c.contributingASNs = asnList[:len(asnList)-1]
+			}
+			return
+		}
+	}
+}
diff --git a/routingtable/locRIB/loc_rib.go b/routingtable/locRIB/loc_rib.go
index ff5750c34d226080bea079968becdec410d2704e..a8ddf1e6a15ff40a6b6f1d6d9f0a643e4e81a20c 100644
--- a/routingtable/locRIB/loc_rib.go
+++ b/routingtable/locRIB/loc_rib.go
@@ -14,19 +14,26 @@ import (
 // LocRIB represents a routing information base
 type LocRIB struct {
 	routingtable.ClientManager
-	rt *routingtable.RoutingTable
-	mu sync.RWMutex
+	rt               *routingtable.RoutingTable
+	mu               sync.RWMutex
+	contributingASNs *routingtable.ContributingASNs
 }
 
 // New creates a new routing information base
 func New() *LocRIB {
 	a := &LocRIB{
-		rt: routingtable.NewRoutingTable(),
+		rt:               routingtable.NewRoutingTable(),
+		contributingASNs: routingtable.NewContributingASNs(),
 	}
 	a.ClientManager = routingtable.NewClientManager(a)
 	return a
 }
 
+// GetContributingASNs returns a pointer to the list of contributing ASNs
+func (a *LocRIB) GetContributingASNs() *routingtable.ContributingASNs {
+	return a.contributingASNs
+}
+
 // UpdateNewClient sends current state to a new client
 func (a *LocRIB) UpdateNewClient(client routingtable.RouteTableClient) error {
 	a.mu.RLock()