diff --git a/config/peer.go b/config/peer.go
index 418d8e00488ddbdde0b6c2cb86b6bcd3e1153644..5bcfa49af2c68951ed5aecb12d2402e6284a42f2 100644
--- a/config/peer.go
+++ b/config/peer.go
@@ -23,4 +23,5 @@ type Peer struct {
 	AddPathRecv       bool
 	ImportFilter      *filter.Filter
 	ExportFilter      *filter.Filter
+	RouteServerClient bool
 }
diff --git a/main.go b/main.go
index e311932915a7f33c7135d45b804ca4ee429a1544..c312e33cbae58d9dafa52c49c813598329cca817 100644
--- a/main.go
+++ b/main.go
@@ -53,8 +53,9 @@ func main() {
 		AddPathSend: routingtable.ClientOptions{
 			MaxPaths: 10,
 		},
-		ImportFilter: filter.NewDrainFilter(),
-		ExportFilter: filter.NewAcceptAllFilter(),
+		ImportFilter:      filter.NewDrainFilter(),
+		ExportFilter:      filter.NewAcceptAllFilter(),
+		RouteServerClient: true,
 	}, rib)
 
 	b.AddPeer(config.Peer{
@@ -71,9 +72,10 @@ func main() {
 		AddPathSend: routingtable.ClientOptions{
 			MaxPaths: 10,
 		},
-		AddPathRecv:  true,
-		ImportFilter: filter.NewAcceptAllFilter(),
-		ExportFilter: filter.NewDrainFilter(),
+		AddPathRecv:       true,
+		ImportFilter:      filter.NewAcceptAllFilter(),
+		ExportFilter:      filter.NewDrainFilter(),
+		RouteServerClient: true,
 	}, rib)
 
 	go func() {
diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go
index ebbb63a24cada154ef7a564b11e39a0c82ee5c8b..80ff7fa7990493186924f8c35f1a90deb0c93e5b 100644
--- a/protocols/bgp/server/fsm_established.go
+++ b/protocols/bgp/server/fsm_established.go
@@ -3,14 +3,14 @@ package server
 import (
 	"bytes"
 	"fmt"
+	"net"
 
-	tnet "github.com/bio-routing/bio-rd/net"
+	bnet "github.com/bio-routing/bio-rd/net"
 	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
 	"github.com/bio-routing/bio-rd/route"
 	"github.com/bio-routing/bio-rd/routingtable"
 	"github.com/bio-routing/bio-rd/routingtable/adjRIBIn"
 	"github.com/bio-routing/bio-rd/routingtable/adjRIBOut"
-	"github.com/bio-routing/bio-rd/routingtable/adjRIBOutAddPath"
 )
 
 type establishedState struct {
@@ -25,7 +25,10 @@ func newEstablishedState(fsm *FSM) *establishedState {
 
 func (s establishedState) run() (state, string) {
 	if !s.fsm.ribsInitialized {
-		s.init()
+		err := s.init()
+		if err != nil {
+			return newCeaseState(), fmt.Sprintf("Init failed: %v", err)
+		}
 	}
 
 	for {
@@ -51,45 +54,51 @@ func (s establishedState) run() (state, string) {
 	}
 }
 
-func (s *establishedState) init() {
-	s.fsm.adjRIBIn = adjRIBIn.New()
+func (s *establishedState) init() error {
+	s.fsm.adjRIBIn = adjRIBIn.New(s.fsm.peer.importFilter)
+	s.fsm.adjRIBIn.Register(s.fsm.rib)
 
-	s.fsm.peer.importFilter.Register(s.fsm.rib)
-	s.fsm.adjRIBIn.Register(s.fsm.peer.importFilter)
+	host, _, err := net.SplitHostPort(s.fsm.con.LocalAddr().String())
+	if err != nil {
+		return fmt.Errorf("Unable to get local address: %v", err)
+	}
+	hostIP := net.ParseIP(host)
+	if hostIP == nil {
+		return fmt.Errorf("Unable to parse address: %v", err)
+	}
 
 	n := &routingtable.Neighbor{
-		Type:     route.BGPPathType,
-		Address:  tnet.IPv4ToUint32(s.fsm.peer.addr),
-		IBGP:     s.fsm.peer.localASN == s.fsm.peer.peerASN,
-		LocalASN: s.fsm.peer.localASN,
+		Type:              route.BGPPathType,
+		Address:           bnet.IPv4ToUint32(s.fsm.peer.addr),
+		IBGP:              s.fsm.peer.localASN == s.fsm.peer.peerASN,
+		LocalASN:          s.fsm.peer.localASN,
+		RouteServerClient: s.fsm.peer.routeServerClient,
+		LocalAddress:      bnet.IPv4ToUint32(hostIP),
+		CapAddPathRX:      s.fsm.capAddPathSend,
 	}
 
+	s.fsm.adjRIBOut = adjRIBOut.New(n, s.fsm.peer.exportFilter)
 	clientOptions := routingtable.ClientOptions{
 		BestOnly: true,
 	}
 	if s.fsm.capAddPathSend {
 		s.fsm.updateSender = newUpdateSenderAddPath(s.fsm)
-		s.fsm.adjRIBOut = adjRIBOutAddPath.New(n)
 		clientOptions = s.fsm.peer.addPathSend
 	} else {
 		s.fsm.updateSender = newUpdateSender(s.fsm)
-		s.fsm.adjRIBOut = adjRIBOut.New(n)
 	}
 
 	s.fsm.adjRIBOut.Register(s.fsm.updateSender)
-	s.fsm.peer.exportFilter.Register(s.fsm.adjRIBOut)
-	s.fsm.rib.RegisterWithOptions(s.fsm.peer.exportFilter, clientOptions)
+	s.fsm.rib.RegisterWithOptions(s.fsm.adjRIBOut, clientOptions)
 
 	s.fsm.ribsInitialized = true
+	return nil
 }
 
 func (s *establishedState) uninit() {
-	s.fsm.adjRIBIn.Unregister(s.fsm.peer.importFilter)
-	s.fsm.peer.importFilter.Unregister(s.fsm.rib)
-
-	s.fsm.rib.Unregister(s.fsm.peer.exportFilter)
-	s.fsm.peer.exportFilter.Unregister(s.fsm.adjRIBOut)
-	s.fsm.updateSender.Unregister(s.fsm.adjRIBOut)
+	s.fsm.adjRIBIn.Unregister(s.fsm.rib)
+	s.fsm.rib.Unregister(s.fsm.adjRIBOut)
+	s.fsm.adjRIBOut.Unregister(s.fsm.updateSender)
 
 	s.fsm.adjRIBIn = nil
 	s.fsm.adjRIBOut = nil
@@ -190,19 +199,19 @@ func (s *establishedState) update(msg *packet.BGPMessage) (state, string) {
 
 func (s *establishedState) withdraws(u *packet.BGPUpdate) {
 	for r := u.WithdrawnRoutes; r != nil; r = r.Next {
-		pfx := tnet.NewPfx(r.IP, r.Pfxlen)
+		pfx := bnet.NewPfx(r.IP, r.Pfxlen)
 		s.fsm.adjRIBIn.RemovePath(pfx, nil)
 	}
 }
 
 func (s *establishedState) updates(u *packet.BGPUpdate) {
 	for r := u.NLRI; r != nil; r = r.Next {
-		pfx := tnet.NewPfx(r.IP, r.Pfxlen)
+		pfx := bnet.NewPfx(r.IP, r.Pfxlen)
 
 		path := &route.Path{
 			Type: route.BGPPathType,
 			BGPPath: &route.BGPPath{
-				Source: tnet.IPv4ToUint32(s.fsm.peer.addr),
+				Source: bnet.IPv4ToUint32(s.fsm.peer.addr),
 			},
 		}
 
diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go
index a0e4c623b5d4d30bdb877311c879b7c568332859..c32315a94a934148a267cf3fa5b90b59794a159f 100644
--- a/protocols/bgp/server/peer.go
+++ b/protocols/bgp/server/peer.go
@@ -28,6 +28,7 @@ type Peer struct {
 	optOpenParams     []packet.OptParam
 	importFilter      *filter.Filter
 	exportFilter      *filter.Filter
+	routeServerClient bool
 }
 
 func (p *Peer) collisionHandling(callingFSM *FSM) bool {
@@ -98,6 +99,7 @@ func NewPeer(c config.Peer, rib routingtable.RouteTableClient, server *BGPServer
 		optOpenParams:     make([]packet.OptParam, 0),
 		importFilter:      filterOrDefault(c.ImportFilter),
 		exportFilter:      filterOrDefault(c.ExportFilter),
+		routeServerClient: c.RouteServerClient,
 	}
 	p.fsms = append(p.fsms, NewActiveFSM2(p))
 
diff --git a/routingtable/adjRIBIn/adj_rib_in.go b/routingtable/adjRIBIn/adj_rib_in.go
index cd4dde58f17e42d9bf75433850dfa39bf2498fbf..ca9d0bb07570811beec3ffa3eb99ec12423f6041 100644
--- a/routingtable/adjRIBIn/adj_rib_in.go
+++ b/routingtable/adjRIBIn/adj_rib_in.go
@@ -3,6 +3,8 @@ package adjRIBIn
 import (
 	"sync"
 
+	"github.com/bio-routing/bio-rd/routingtable/filter"
+
 	"github.com/bio-routing/bio-rd/net"
 	"github.com/bio-routing/bio-rd/route"
 	"github.com/bio-routing/bio-rd/routingtable"
@@ -12,14 +14,16 @@ import (
 // AdjRIBIn represents an Adjacency RIB In as described in RFC4271
 type AdjRIBIn struct {
 	routingtable.ClientManager
-	rt *routingtable.RoutingTable
-	mu sync.RWMutex
+	rt           *routingtable.RoutingTable
+	mu           sync.RWMutex
+	exportFilter *filter.Filter
 }
 
 // New creates a new Adjacency RIB In
-func New() *AdjRIBIn {
+func New(exportFilter *filter.Filter) *AdjRIBIn {
 	a := &AdjRIBIn{
-		rt: routingtable.NewRoutingTable(),
+		rt:           routingtable.NewRoutingTable(),
+		exportFilter: exportFilter,
 	}
 	a.ClientManager = routingtable.NewClientManager(a)
 	return a
@@ -34,6 +38,10 @@ func (a *AdjRIBIn) UpdateNewClient(client routingtable.RouteTableClient) error {
 	for _, route := range routes {
 		paths := route.Paths()
 		for _, path := range paths {
+			path, reject := a.exportFilter.ProcessTerms(route.Prefix(), path)
+			if reject {
+				continue
+			}
 
 			err := client.AddPath(route.Prefix(), path)
 			if err != nil {
@@ -52,6 +60,11 @@ func (a *AdjRIBIn) AddPath(pfx net.Prefix, p *route.Path) error {
 	oldPaths := a.rt.ReplacePath(pfx, p)
 	a.removePathsFromClients(pfx, oldPaths)
 
+	p, reject := a.exportFilter.ProcessTerms(pfx, p)
+	if reject {
+		return nil
+	}
+
 	for _, client := range a.ClientManager.Clients() {
 		client.AddPath(pfx, p)
 	}
@@ -79,6 +92,10 @@ func (a *AdjRIBIn) RemovePath(pfx net.Prefix, p *route.Path) bool {
 
 func (a *AdjRIBIn) removePathsFromClients(pfx net.Prefix, paths []*route.Path) {
 	for _, path := range paths {
+		path, reject := a.exportFilter.ProcessTerms(pfx, path)
+		if reject {
+			continue
+		}
 		for _, client := range a.ClientManager.Clients() {
 			client.RemovePath(pfx, path)
 		}
diff --git a/routingtable/adjRIBIn/adj_rib_in_test.go b/routingtable/adjRIBIn/adj_rib_in_test.go
index a994e0f5e82be4ccef141ce63463b762d055d111..48ac1fdb3efbe6c4aac8c0cbbef8371f1dc691af 100644
--- a/routingtable/adjRIBIn/adj_rib_in_test.go
+++ b/routingtable/adjRIBIn/adj_rib_in_test.go
@@ -4,6 +4,8 @@ import (
 	"fmt"
 	"testing"
 
+	"github.com/bio-routing/bio-rd/routingtable/filter"
+
 	"github.com/stretchr/testify/assert"
 
 	"github.com/bio-routing/bio-rd/net"
@@ -113,7 +115,7 @@ func TestAddPath(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		adjRIBIn := New()
+		adjRIBIn := New(filter.NewAcceptAllFilter())
 		mc := NewRTMockClient()
 		adjRIBIn.ClientManager.Register(mc)
 
@@ -204,7 +206,7 @@ func TestRemovePath(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		adjRIBIn := New()
+		adjRIBIn := New(filter.NewAcceptAllFilter())
 		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
deleted file mode 100644
index 5c15e446f20692c4375ea2b27aa8061fca32faf4..0000000000000000000000000000000000000000
--- a/routingtable/adjRIBOut/adj_rib_out.go
+++ /dev/null
@@ -1,105 +0,0 @@
-package adjRIBOut
-
-import (
-	"fmt"
-	"sync"
-
-	"github.com/bio-routing/bio-rd/net"
-	"github.com/bio-routing/bio-rd/route"
-	"github.com/bio-routing/bio-rd/routingtable"
-	log "github.com/sirupsen/logrus"
-)
-
-// AdjRIBOut represents an Adjacency RIB In as described in RFC4271
-type AdjRIBOut struct {
-	routingtable.ClientManager
-	rt       *routingtable.RoutingTable
-	neighbor *routingtable.Neighbor
-	mu       sync.RWMutex
-}
-
-// New creates a new Adjacency RIB In
-func New(neighbor *routingtable.Neighbor) *AdjRIBOut {
-	a := &AdjRIBOut{
-		rt:       routingtable.NewRoutingTable(),
-		neighbor: neighbor,
-	}
-	a.ClientManager = routingtable.NewClientManager(a)
-	return a
-}
-
-// UpdateNewClient sends current state to a new client
-func (a *AdjRIBOut) UpdateNewClient(client routingtable.RouteTableClient) error {
-	return nil
-}
-
-// AddPath replaces the path for prefix `pfx`. If the prefix doesn't exist it is added.
-func (a *AdjRIBOut) AddPath(pfx net.Prefix, p *route.Path) error {
-	if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
-		return nil
-	}
-
-	p = p.Copy()
-	if !a.neighbor.IBGP {
-		p.BGPPath.ASPath = fmt.Sprintf("%d %s", a.neighbor.LocalASN, p.BGPPath.ASPath)
-	}
-
-	a.mu.Lock()
-	defer a.mu.Unlock()
-
-	oldPaths := a.rt.ReplacePath(pfx, p)
-	a.removePathsFromClients(pfx, oldPaths)
-
-	for _, client := range a.ClientManager.Clients() {
-		err := client.AddPath(pfx, p)
-		if err != nil {
-			log.WithField("Sender", "AdjRIBOut").WithError(err).Error("Could not send update to client")
-		}
-	}
-	return nil
-}
-
-// RemovePath removes the path for prefix `pfx`
-func (a *AdjRIBOut) RemovePath(pfx net.Prefix, p *route.Path) bool {
-	if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
-		return false
-	}
-
-	a.mu.Lock()
-	defer a.mu.Unlock()
-
-	r := a.rt.Get(pfx)
-	if r == nil {
-		return false
-	}
-
-	oldPaths := r.Paths()
-	for _, path := range oldPaths {
-		a.rt.RemovePath(pfx, path)
-	}
-
-	a.removePathsFromClients(pfx, oldPaths)
-	return true
-}
-
-func (a *AdjRIBOut) removePathsFromClients(pfx net.Prefix, paths []*route.Path) {
-	for _, path := range paths {
-		for _, client := range a.ClientManager.Clients() {
-			client.RemovePath(pfx, path)
-		}
-	}
-}
-
-// Print dumps all prefixes in the Adj-RIB
-func (a *AdjRIBOut) Print() string {
-	a.mu.RLock()
-	defer a.mu.RUnlock()
-
-	ret := fmt.Sprintf("DUMPING ADJ-RIB-OUT:\n")
-	routes := a.rt.Dump()
-	for _, r := range routes {
-		ret += fmt.Sprintf("%s\n", r.Prefix().String())
-	}
-
-	return ret
-}
diff --git a/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go b/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go
deleted file mode 100644
index 30c20c4bc8b612e8788838da5a0180fa4f3d3166..0000000000000000000000000000000000000000
--- a/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go
+++ /dev/null
@@ -1,120 +0,0 @@
-package adjRIBOutAddPath
-
-import (
-	"fmt"
-	"sync"
-
-	"github.com/bio-routing/bio-rd/net"
-	"github.com/bio-routing/bio-rd/route"
-	"github.com/bio-routing/bio-rd/routingtable"
-	log "github.com/sirupsen/logrus"
-)
-
-// AdjRIBOutAddPath represents an Adjacency RIB Out with BGP add path
-type AdjRIBOutAddPath struct {
-	routingtable.ClientManager
-	rt            *routingtable.RoutingTable
-	neighbor      *routingtable.Neighbor
-	pathIDManager *pathIDManager
-	mu            sync.RWMutex
-}
-
-// New creates a new Adjacency RIB Out with BGP add path
-func New(neighbor *routingtable.Neighbor) *AdjRIBOutAddPath {
-	a := &AdjRIBOutAddPath{
-		rt:            routingtable.NewRoutingTable(),
-		neighbor:      neighbor,
-		pathIDManager: newPathIDManager(),
-	}
-	a.ClientManager = routingtable.NewClientManager(a)
-	return a
-}
-
-// UpdateNewClient sends current state to a new client
-func (a *AdjRIBOutAddPath) UpdateNewClient(client routingtable.RouteTableClient) error {
-	return nil
-}
-
-// AddPath adds path p to prefix `pfx`
-func (a *AdjRIBOutAddPath) AddPath(pfx net.Prefix, p *route.Path) error {
-	if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
-		return nil
-	}
-
-	p = p.Copy()
-	if !a.neighbor.IBGP {
-		p.BGPPath.ASPath = fmt.Sprintf("%d %s", a.neighbor.LocalASN, p.BGPPath.ASPath)
-	}
-
-	a.mu.Lock()
-	defer a.mu.Unlock()
-
-	pathID, err := a.pathIDManager.getNewID()
-	if err != nil {
-		return fmt.Errorf("Unable to get path ID: %v", err)
-	}
-
-	p.BGPPath.PathIdentifier = pathID
-	a.rt.AddPath(pfx, p)
-
-	for _, client := range a.ClientManager.Clients() {
-		err := client.AddPath(pfx, p)
-		if err != nil {
-			log.WithField("Sender", "AdjRIBOutAddPath").WithError(err).Error("Could not send update to client")
-		}
-	}
-	return nil
-}
-
-// RemovePath removes the path for prefix `pfx`
-func (a *AdjRIBOutAddPath) RemovePath(pfx net.Prefix, p *route.Path) bool {
-	if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
-		return false
-	}
-
-	a.mu.Lock()
-	defer a.mu.Unlock()
-
-	r := a.rt.Get(pfx)
-	if r == nil {
-		return false
-	}
-
-	a.rt.RemovePath(pfx, p)
-	a.pathIDManager.releaseID(p.BGPPath.PathIdentifier)
-	a.removePathFromClients(pfx, p)
-	return true
-}
-
-func (a *AdjRIBOutAddPath) isOwnPath(p *route.Path) bool {
-	if p.Type != a.neighbor.Type {
-		return false
-	}
-
-	switch p.Type {
-	case route.BGPPathType:
-		return p.BGPPath.Source == a.neighbor.Address
-	}
-
-	return false
-}
-
-func (a *AdjRIBOutAddPath) removePathFromClients(pfx net.Prefix, path *route.Path) {
-	for _, client := range a.ClientManager.Clients() {
-		client.RemovePath(pfx, path)
-	}
-}
-
-// Print dumps all prefixes in the Adj-RIB
-func (a *AdjRIBOutAddPath) Print() string {
-	a.mu.RLock()
-	defer a.mu.RUnlock()
-
-	ret := fmt.Sprintf("DUMPING ADJ-RIB-OUT:\n")
-	routes := a.rt.Dump()
-	for _, r := range routes {
-		ret += fmt.Sprintf("%s\n", r.Prefix().String())
-	}
-
-	return ret
-}
diff --git a/routingtable/adjRIBOutAddPath/path_id_manager.go b/routingtable/adjRIBOutAddPath/path_id_manager.go
deleted file mode 100644
index 0d79924941424b3cb7a772a6ca3df07ce914fb6e..0000000000000000000000000000000000000000
--- a/routingtable/adjRIBOutAddPath/path_id_manager.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package adjRIBOutAddPath
-
-import (
-	"fmt"
-)
-
-var maxUint32 = ^uint32(0)
-
-// pathIDManager manages BGP path identifiers for add-path. This is no thread safe (and doesn't need to be).
-type pathIDManager struct {
-	ids  map[uint32]struct{}
-	last uint32
-	used uint32
-}
-
-func newPathIDManager() *pathIDManager {
-	return &pathIDManager{
-		ids: make(map[uint32]struct{}),
-	}
-}
-
-func (fm *pathIDManager) getNewID() (uint32, error) {
-	if fm.used == maxUint32 {
-		return 0, fmt.Errorf("Out of path IDs")
-	}
-
-	fm.last++
-	for {
-		if _, exists := fm.ids[fm.last]; exists {
-			fm.last++
-			continue
-		}
-		break
-	}
-
-	ret := fm.last
-	fm.used++
-
-	return ret, nil
-}
-
-func (fm *pathIDManager) releaseID(id uint32) {
-	if _, exists := fm.ids[id]; exists {
-		delete(fm.ids, id)
-		fm.used--
-	}
-}
diff --git a/routingtable/adjRIBOutAddPath/path_id_manager_test.go b/routingtable/adjRIBOutAddPath/path_id_manager_test.go
deleted file mode 100644
index c1cff4e6060b26075c99c957ae500fc74484f613..0000000000000000000000000000000000000000
--- a/routingtable/adjRIBOutAddPath/path_id_manager_test.go
+++ /dev/null
@@ -1,109 +0,0 @@
-package adjRIBOutAddPath
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestGetNewID(t *testing.T) {
-	tests := []struct {
-		name     string
-		maxIDs   uint32
-		count    int
-		wantFail bool
-	}{
-		{
-			name:     "Out of path IDs",
-			maxIDs:   10,
-			count:    11,
-			wantFail: true,
-		},
-		{
-			name:     "Success",
-			maxIDs:   10,
-			count:    10,
-			wantFail: false,
-		},
-	}
-
-X:
-	for _, test := range tests {
-		maxUint32 = test.maxIDs
-		m := newPathIDManager()
-		for i := 0; i < test.count; i++ {
-			_, err := m.getNewID()
-			if err != nil {
-				if test.wantFail {
-					continue X
-				}
-
-				t.Errorf("Unexpected failure for test %q: %v", test.name, err)
-				continue X
-			}
-		}
-
-		if test.wantFail {
-			t.Errorf("Unexpected success for test %q", test.name)
-			continue
-		}
-	}
-}
-
-func TestReleaseID(t *testing.T) {
-	tests := []struct {
-		name     string
-		pm       *pathIDManager
-		release  uint32
-		expected *pathIDManager
-	}{
-		{
-			name: "Release existent",
-			pm: &pathIDManager{
-				ids: map[uint32]struct{}{
-					0: struct{}{},
-					1: struct{}{},
-					2: struct{}{},
-				},
-				last: 2,
-				used: 3,
-			},
-			release: 1,
-			expected: &pathIDManager{
-				ids: map[uint32]struct{}{
-					0: struct{}{},
-					2: struct{}{},
-				},
-				last: 2,
-				used: 2,
-			},
-		},
-		{
-			name: "Release non-existent",
-			pm: &pathIDManager{
-				ids: map[uint32]struct{}{
-					0: struct{}{},
-					1: struct{}{},
-					2: struct{}{},
-				},
-				last: 2,
-				used: 3,
-			},
-			release: 3,
-			expected: &pathIDManager{
-				ids: map[uint32]struct{}{
-					0: struct{}{},
-					1: struct{}{},
-					2: struct{}{},
-				},
-				last: 2,
-				used: 3,
-			},
-		},
-	}
-
-	for _, test := range tests {
-		test.pm.releaseID(test.release)
-		assert.Equalf(t, test.expected, test.pm, "%s", test.name)
-	}
-}
diff --git a/routingtable/filter/filter.go b/routingtable/filter/filter.go
index f2b46997bd2d02a0c7e03d5bc0e4faccf180c9e7..cb88087983c31ebb2a5b58bf7a002117c829efb7 100644
--- a/routingtable/filter/filter.go
+++ b/routingtable/filter/filter.go
@@ -3,11 +3,9 @@ package filter
 import (
 	"github.com/bio-routing/bio-rd/net"
 	"github.com/bio-routing/bio-rd/route"
-	"github.com/bio-routing/bio-rd/routingtable"
 )
 
 type Filter struct {
-	routingtable.ClientManager
 	terms []*Term
 }
 
@@ -15,42 +13,11 @@ func NewFilter(terms []*Term) *Filter {
 	f := &Filter{
 		terms: terms,
 	}
-	f.ClientManager = routingtable.NewClientManager(f)
 
 	return f
 }
 
-func (f *Filter) AddPath(p net.Prefix, pa *route.Path) error {
-	pa, rejected := f.processTerms(p, pa)
-	if rejected {
-		return nil
-	}
-
-	for _, c := range f.Clients() {
-		c.AddPath(p, pa)
-	}
-
-	return nil
-}
-
-func (f *Filter) RemovePath(p net.Prefix, pa *route.Path) bool {
-	pa, rejected := f.processTerms(p, pa)
-	if rejected {
-		return false
-	}
-
-	for _, c := range f.Clients() {
-		c.RemovePath(p, pa)
-	}
-
-	return true
-}
-
-func (f *Filter) UpdateNewClient(c routingtable.RouteTableClient) error {
-	return nil
-}
-
-func (f *Filter) processTerms(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) {
+func (f *Filter) ProcessTerms(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) {
 	modPath = pa
 
 	for _, t := range f.terms {
diff --git a/routingtable/filter/filter_test.go b/routingtable/filter/filter_test.go
index ce9b733e08a0b32959eb23b3230ffeb7cb5c3041..2f4aace7637f30095d106520495d12a2d3ad9626 100644
--- a/routingtable/filter/filter_test.go
+++ b/routingtable/filter/filter_test.go
@@ -1,46 +1,6 @@
 package filter
 
-import (
-	"testing"
-
-	"github.com/bio-routing/bio-rd/routingtable/filter/actions"
-	"github.com/stretchr/testify/assert"
-
-	"github.com/bio-routing/bio-rd/net"
-	"github.com/bio-routing/bio-rd/route"
-	"github.com/bio-routing/bio-rd/routingtable"
-)
-
-type clientMock struct {
-	routingtable.ClientManager
-	addPathCalled    bool
-	removePathCalled bool
-	path             *route.Path
-}
-
-func (m *clientMock) AddPath(p net.Prefix, pa *route.Path) error {
-	m.path = pa
-	m.addPathCalled = true
-	return nil
-}
-
-func (m *clientMock) RemovePath(p net.Prefix, pa *route.Path) bool {
-	m.path = pa
-	m.removePathCalled = true
-	return false
-}
-
-func (m *clientMock) UpdateNewClient(c routingtable.RouteTableClient) error {
-	return nil
-}
-
-func newClientMock() *clientMock {
-	m := &clientMock{}
-	m.ClientManager = routingtable.NewClientManager(m)
-	return m
-}
-
-func TestAddPath(t *testing.T) {
+/*func TestAddPath(t *testing.T) {
 	tests := []struct {
 		name           string
 		prefix         net.Prefix
@@ -184,4 +144,4 @@ func TestRemovePath(t *testing.T) {
 			}
 		})
 	}
-}
+}*/
diff --git a/routingtable/filter/helper_test.go b/routingtable/filter/helper_test.go
index a0370e7677aa303dcc2efc5d0242f2f287222d9a..5d82727a9f2b5b5e0f692a980d9d7515ccd4c71d 100644
--- a/routingtable/filter/helper_test.go
+++ b/routingtable/filter/helper_test.go
@@ -1,13 +1,6 @@
 package filter
 
-import (
-	"testing"
-
-	"github.com/bio-routing/bio-rd/net"
-	"github.com/bio-routing/bio-rd/route"
-)
-
-func TestNewAcceptAllFilter(t *testing.T) {
+/*func TestNewAcceptAllFilter(t *testing.T) {
 	f := NewAcceptAllFilter()
 
 	m := &clientMock{}
@@ -31,4 +24,4 @@ func TestNewDrainFilter(t *testing.T) {
 	if m.addPathCalled {
 		t.Fatalf("expected filtered, but was accepted")
 	}
-}
+}*/
diff --git a/routingtable/neighbor.go b/routingtable/neighbor.go
index 11b8c8de65a54e768c4a852cb87dcbfe44d6c55a..f298356fa73ef40de0293b76d55c28cc0c363dfe 100644
--- a/routingtable/neighbor.go
+++ b/routingtable/neighbor.go
@@ -5,6 +5,9 @@ type Neighbor struct {
 	// Addres is the IPv4 address of the neighbor as integer representation
 	Address uint32
 
+	// Local address is the local address of the BGP TCP connection
+	LocalAddress uint32
+
 	// Type is the type / protocol used for routing inforation communitation
 	Type uint8
 
@@ -13,4 +16,10 @@ type Neighbor struct {
 
 	// Local ASN of session
 	LocalASN uint32
+
+	// Peer is a route server client
+	RouteServerClient bool
+
+	// CapAddPathRX indicates if the peer supports receiving multiple BGP paths
+	CapAddPathRX bool
 }