diff --git a/protocols/bgp/server/bmp_router.go b/protocols/bgp/server/bmp_router.go
index 08bc38f2f6796edddaaa2e5e34c42f4486ff14fc..46f0f0a80230acf1e2ae9ceb73fab4febafef723 100644
--- a/protocols/bgp/server/bmp_router.go
+++ b/protocols/bgp/server/bmp_router.go
@@ -58,7 +58,8 @@ func newRouter(addr net.IP, port uint16, rib4 *locRIB.LocRIB, rib6 *locRIB.LocRI
 	}
 }
 
-func (r *router) serve() {
+func (r *router) serve(con net.Conn) {
+	r.con = con
 	r.runMu.Lock()
 	defer r.con.Close()
 	defer r.runMu.Unlock()
@@ -176,8 +177,7 @@ func (r *router) processTerminationMsg(msg *bmppkt.TerminationMessage) {
 
 	r.con.Close()
 	for n := range r.neighbors {
-		// TODO: Cleanup after neighbors
-		delete(r.neighbors, n)
+		r.peerDown(n)
 	}
 }
 
@@ -190,8 +190,21 @@ func (r *router) processPeerDownNotification(msg *bmppkt.PeerDownNotification) {
 		return
 	}
 
-	delete(r.neighbors, msg.PerPeerHeader.PeerAddress)
-	// TODO: Cleanup after neighbor
+	r.peerDown(msg.PerPeerHeader.PeerAddress)
+}
+
+func (r *router) peerDown(addr [16]byte) {
+	if r.neighbors[addr].fsm != nil {
+		if r.neighbors[addr].fsm.ipv4Unicast != nil {
+			r.neighbors[addr].fsm.ipv4Unicast.bmpDispose()
+		}
+
+		if r.neighbors[addr].fsm.ipv6Unicast != nil {
+			r.neighbors[addr].fsm.ipv6Unicast.bmpDispose()
+		}
+	}
+
+	delete(r.neighbors, addr)
 }
 
 func (r *router) processPeerUpNotification(msg *bmppkt.PeerUpNotification) error {
diff --git a/protocols/bgp/server/bmp_router_test.go b/protocols/bgp/server/bmp_router_test.go
index 3b585c3780b8b8f4318f98440b1ac80ce1996f73..7ccd96b638d291271079128a37be18f2c326843f 100644
--- a/protocols/bgp/server/bmp_router_test.go
+++ b/protocols/bgp/server/bmp_router_test.go
@@ -17,6 +17,54 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+func TestBMPRouterServe(t *testing.T) {
+	tests := []struct {
+		name     string
+		msg      []byte
+		wantFail bool
+	}{
+		{
+			name:     "Test #1",
+			msg:      []byte{1, 2, 3},
+			wantFail: true,
+		},
+	}
+
+	for _, test := range tests {
+		addr := net.IP{10, 20, 30, 40}
+		port := uint16(123)
+		rib4 := locRIB.New()
+		rib6 := locRIB.New()
+		conA, conB := net.Pipe()
+
+		r := newRouter(addr, port, rib4, rib6)
+		buf := bytes.NewBuffer(nil)
+		r.logger.Out = buf
+		go r.serve(conA)
+
+		conB.Write(test.msg)
+
+		assert.Equalf(t, 0, len(buf.Bytes()), "Test %q", test.name)
+	}
+}
+
+func TestStartStopBMP(t *testing.T) {
+	addr := net.IP{10, 20, 30, 40}
+	port := uint16(123)
+	rib4 := locRIB.New()
+	rib6 := locRIB.New()
+
+	con := biotesting.NewMockConn()
+
+	r := newRouter(addr, port, rib4, rib6)
+	go r.serve(con)
+
+	r.stop <- struct{}{}
+
+	r.runMu.Lock()
+	assert.Equal(t, true, r.con.(*biotesting.MockConn).Closed)
+}
+
 func TestConfigureBySentOpen(t *testing.T) {
 	tests := []struct {
 		name     string
diff --git a/protocols/bgp/server/bmp_server.go b/protocols/bgp/server/bmp_server.go
index cff9f709d5c900afc9a7dce082df2679d67d133f..100e514cd7a0aebbd4e88de8ae2ac7c670440433 100644
--- a/protocols/bgp/server/bmp_server.go
+++ b/protocols/bgp/server/bmp_server.go
@@ -7,7 +7,7 @@ import (
 	"sync"
 	"time"
 
-	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
+	bmppkt "github.com/bio-routing/bio-rd/protocols/bmp/packet"
 	"github.com/bio-routing/bio-rd/routingtable/locRIB"
 	log "github.com/sirupsen/logrus"
 	"github.com/taktv6/tflow2/convert"
@@ -55,9 +55,8 @@ func (b *BMPServer) AddRouter(addr net.IP, port uint16, rib4 *locRIB.LocRIB, rib
 			}
 
 			r.reconnectTime = 0
-			r.con = c
 			log.Infof("Connected to %s", r.address.String())
-			r.serve()
+			r.serve(c)
 		}
 	}(r)
 }
@@ -75,7 +74,7 @@ func (b *BMPServer) RemoveRouter(addr net.IP, port uint16) {
 
 func recvBMPMsg(c net.Conn) (msg []byte, err error) {
 	buffer := make([]byte, defaultBufferLen)
-	_, err = io.ReadFull(c, buffer[0:packet.MinLen])
+	_, err = io.ReadFull(c, buffer[0:bmppkt.MinLen])
 	if err != nil {
 		return nil, fmt.Errorf("Read failed: %v", err)
 	}
@@ -88,7 +87,7 @@ func recvBMPMsg(c net.Conn) (msg []byte, err error) {
 	}
 
 	toRead := l
-	_, err = io.ReadFull(c, buffer[packet.MinLen:toRead])
+	_, err = io.ReadFull(c, buffer[bmppkt.MinLen:toRead])
 	if err != nil {
 		return nil, fmt.Errorf("Read failed: %v", err)
 	}
diff --git a/protocols/bgp/server/bmp_server_test.go b/protocols/bgp/server/bmp_server_test.go
index 3ebef9a2535e35ecdedf1a4a560003ff3fd37c17..e2853952e6bdf949839af899bebe515bb279ad53 100644
--- a/protocols/bgp/server/bmp_server_test.go
+++ b/protocols/bgp/server/bmp_server_test.go
@@ -6,6 +6,7 @@ import (
 	"time"
 
 	"github.com/bio-routing/bio-rd/routingtable/locRIB"
+	biotesting "github.com/bio-routing/bio-rd/testing"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -16,7 +17,7 @@ func TestNewServer(t *testing.T) {
 	}, s)
 }
 
-func TestIntegration(t *testing.T) {
+func TestIntegrationPeerUpRouteMonitor(t *testing.T) {
 	addr := net.IP{10, 20, 30, 40}
 	port := uint16(12346)
 
@@ -25,9 +26,8 @@ func TestIntegration(t *testing.T) {
 
 	r := newRouter(addr, port, rib4, rib6)
 	conA, conB := net.Pipe()
-	r.con = conB
 
-	go r.serve()
+	go r.serve(conB)
 
 	// Peer Up Notification
 	_, err := conA.Write([]byte{
@@ -134,16 +134,12 @@ func TestIntegration(t *testing.T) {
 	})
 
 	if err != nil {
-		panic("write #1 failed")
+		panic("write failed")
 	}
 
 	time.Sleep(time.Millisecond * 50)
 	assert.NotEmpty(t, r.neighbors)
 
-	if err != nil {
-		panic("Write #2 failed")
-	}
-
 	time.Sleep(time.Millisecond * 50)
 
 	count := rib4.RouteCount()
@@ -153,3 +149,562 @@ func TestIntegration(t *testing.T) {
 
 	conA.Close()
 }
+
+func TestIntegrationIncompleteBMPMsg(t *testing.T) {
+	addr := net.IP{10, 20, 30, 40}
+	port := uint16(12346)
+
+	rib4 := locRIB.New()
+	rib6 := locRIB.New()
+
+	r := newRouter(addr, port, rib4, rib6)
+	con := biotesting.NewMockConn()
+
+	// Peer Up Notification with invalid version number (4)
+	con.Write([]byte{
+		// Common Header
+		4,            // Version
+		0, 0, 0, 126, // Message Length
+		3, // Msg Type = Peer Up Notification
+
+		// Per Peer Header
+		0,                      // Peer Type
+		0,                      // Peer Flags
+		0, 0, 0, 0, 0, 0, 0, 0, // Peer Distinguisher
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 40, // 10.20.30.40 peer address
+		0, 0, 0, 100, // Peer AS
+		0, 0, 0, 255, // Peer BGP ID
+		0, 0, 0, 0, // Timestamp s
+		0, 0, 0, 0, // Timestamp µs
+
+		// Peer Up Notification
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 41, // 10.20.30.41 local address
+		0, 123, // Local Port
+		0, 234, // Remote Port
+
+		// Sent OPEN message
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 29, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 200, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 1, // BGP Identifier
+		0, // Opt param length
+
+		// Received OPEN message
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 29, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 100, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 255, // BGP Identifier
+		0, // Opt param length
+
+		// SECOND MESSAGE:
+
+		// Common Header
+		3,            // Version
+		0, 0, 0, 116, // Message Length
+		0, // Msg Type = Route Monitoring Message
+
+		// Per Peer Header
+		0,                      // Peer Type
+		0,                      // Peer Flags
+		0, 0, 0, 0, 0, 0, 0, 0, // Peer Distinguisher
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 40, // 10.20.30.40 peer address
+		0, 0, 0, 100, // Peer AS
+		0, 0, 0, 255, // Peer BGP ID
+		0, 0, 0, 0, // Timestamp s
+		0, 0, 0, 0, // Timestamp µs
+
+	})
+
+	r.serve(con)
+
+	if !con.Closed {
+		t.Errorf("Connection not closed although failure should have happened")
+	}
+}
+
+func TestBMPFullRunWithWithdraw(t *testing.T) {
+	addr := net.IP{10, 20, 30, 40}
+	port := uint16(12346)
+
+	rib4 := locRIB.New()
+	rib6 := locRIB.New()
+
+	r := newRouter(addr, port, rib4, rib6)
+	con := biotesting.NewMockConn()
+
+	go r.serve(con)
+
+	con.Write([]byte{
+		// #####################################################################
+		// Initiation Message
+		// #####################################################################
+		// Common Header
+		3,
+		0, 0, 0, 23,
+		4,
+		0, 1, // sysDescr
+		0, 4, // Length
+		42, 42, 42, 42, // AAAA
+		0, 2, //sysName
+		0, 5, // Length
+		43, 43, 43, 43, 43, // BBBBB
+
+		// #####################################################################
+		// Peer UP Notification
+		// #####################################################################
+		// Common Header
+		3,            // Version
+		0, 0, 0, 126, // Message Length
+		3, // Msg Type = Peer Up Notification
+		// Per Peer Header
+		0,                      // Peer Type
+		0,                      // Peer Flags
+		0, 0, 0, 0, 0, 0, 0, 0, // Peer Distinguisher
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 40, // 10.20.30.40 peer address
+		0, 0, 0, 100, // Peer AS
+		0, 0, 0, 255, // Peer BGP ID
+		0, 0, 0, 0, // Timestamp s
+		0, 0, 0, 0, // Timestamp µs
+		// Peer Up Notification
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 41, // 10.20.30.41 local address
+		0, 123, // Local Port
+		0, 234, // Remote Port
+		// Sent OPEN message
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 29, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 200, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 1, // BGP Identifier
+		0, // Opt param length
+		// Received OPEN message
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 29, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 100, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 255, // BGP Identifier
+		0, // Opt param length
+
+		// #####################################################################
+		// Route Monitoring Message #1
+		// #####################################################################
+		// Common Header
+		3,            // Version
+		0, 0, 0, 116, // Message Length
+		0, // Msg Type = Route Monitoring Message
+
+		// Per Peer Header
+		0,                      // Peer Type
+		0,                      // Peer Flags
+		0, 0, 0, 0, 0, 0, 0, 0, // Peer Distinguisher
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 40, // 10.20.30.40 peer address
+		0, 0, 0, 100, // Peer AS
+		0, 0, 0, 255, // Peer BGP ID
+		0, 0, 0, 0, // Timestamp s
+		0, 0, 0, 0, // Timestamp µs
+
+		// BGP Update
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 68, // Length
+		2, // Update
+
+		0, 0, // Withdrawn Routes Length
+		0, 41, // Total Path Attribute Length
+
+		255,  // Attribute flags
+		1,    // Attribute Type code (ORIGIN)
+		0, 1, // Length
+		2, // INCOMPLETE
+
+		0,      // Attribute flags
+		2,      // Attribute Type code (AS Path)
+		12,     // Length
+		2,      // Type = AS_SEQUENCE
+		2,      // Path Segment Length
+		59, 65, // AS15169
+		12, 248, // AS3320
+		1,      // Type = AS_SET
+		2,      // Path Segment Length
+		59, 65, // AS15169
+		12, 248, // AS3320
+
+		0,              // Attribute flags
+		3,              // Attribute Type code (Next Hop)
+		4,              // Length
+		10, 11, 12, 13, // Next Hop
+
+		0,          // Attribute flags
+		4,          // Attribute Type code (MED)
+		4,          // Length
+		0, 0, 1, 0, // MED 256
+
+		0,          // Attribute flags
+		5,          // Attribute Type code (Local Pref)
+		4,          // Length
+		0, 0, 1, 0, // Local Pref 256
+
+		// NLRI
+		24,
+		192, 168, 0,
+
+		// #####################################################################
+		// Route Monitoring Message #2 (withdraw of prefix from #1)
+		// #####################################################################
+		// Common Header
+		3,           // Version
+		0, 0, 0, 75, // Message Length
+		0, // Msg Type = Route Monitoring Message
+
+		// Per Peer Header
+		0,                      // Peer Type
+		0,                      // Peer Flags
+		0, 0, 0, 0, 0, 0, 0, 0, // Peer Distinguisher
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 40, // 10.20.30.40 peer address
+		0, 0, 0, 100, // Peer AS
+		0, 0, 0, 255, // Peer BGP ID
+		0, 0, 0, 0, // Timestamp s
+		0, 0, 0, 0, // Timestamp µs
+
+		// BGP Update
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 27, // Length
+		2, // Update
+
+		0, 4, // Withdrawn Routes Length
+		24,
+		192, 168, 0,
+		0, 0, // Total Path Attribute Length
+	})
+
+	time.Sleep(time.Millisecond * 50)
+	assert.NotEmpty(t, r.neighbors)
+
+	time.Sleep(time.Millisecond * 50)
+
+	count := rib4.RouteCount()
+	if count != 0 {
+		t.Errorf("Unexpected route count. Expected: 0 Got: %d", count)
+	}
+
+}
+
+func TestBMPFullRunWithPeerDownNotification(t *testing.T) {
+	addr := net.IP{10, 20, 30, 40}
+	port := uint16(12346)
+
+	rib4 := locRIB.New()
+	rib6 := locRIB.New()
+
+	r := newRouter(addr, port, rib4, rib6)
+	con := biotesting.NewMockConn()
+
+	go r.serve(con)
+
+	con.Write([]byte{
+		// #####################################################################
+		// Initiation Message
+		// #####################################################################
+		// Common Header
+		3,
+		0, 0, 0, 23,
+		4,
+		0, 1, // sysDescr
+		0, 4, // Length
+		42, 42, 42, 42, // AAAA
+		0, 2, //sysName
+		0, 5, // Length
+		43, 43, 43, 43, 43, // BBBBB
+
+		// #####################################################################
+		// Peer UP Notification
+		// #####################################################################
+		// Common Header
+		3,            // Version
+		0, 0, 0, 126, // Message Length
+		3, // Msg Type = Peer Up Notification
+		// Per Peer Header
+		0,                      // Peer Type
+		0,                      // Peer Flags
+		0, 0, 0, 0, 0, 0, 0, 0, // Peer Distinguisher
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 40, // 10.20.30.40 peer address
+		0, 0, 0, 100, // Peer AS
+		0, 0, 0, 255, // Peer BGP ID
+		0, 0, 0, 0, // Timestamp s
+		0, 0, 0, 0, // Timestamp µs
+		// Peer Up Notification
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 41, // 10.20.30.41 local address
+		0, 123, // Local Port
+		0, 234, // Remote Port
+		// Sent OPEN message
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 29, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 200, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 1, // BGP Identifier
+		0, // Opt param length
+		// Received OPEN message
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 29, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 100, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 255, // BGP Identifier
+		0, // Opt param length
+
+		// #####################################################################
+		// Route Monitoring Message #1
+		// #####################################################################
+		// Common Header
+		3,            // Version
+		0, 0, 0, 116, // Message Length
+		0, // Msg Type = Route Monitoring Message
+
+		// Per Peer Header
+		0,                      // Peer Type
+		0,                      // Peer Flags
+		0, 0, 0, 0, 0, 0, 0, 0, // Peer Distinguisher
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 40, // 10.20.30.40 peer address
+		0, 0, 0, 100, // Peer AS
+		0, 0, 0, 255, // Peer BGP ID
+		0, 0, 0, 0, // Timestamp s
+		0, 0, 0, 0, // Timestamp µs
+
+		// BGP Update
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 68, // Length
+		2, // Update
+
+		0, 0, // Withdrawn Routes Length
+		0, 41, // Total Path Attribute Length
+
+		255,  // Attribute flags
+		1,    // Attribute Type code (ORIGIN)
+		0, 1, // Length
+		2, // INCOMPLETE
+
+		0,      // Attribute flags
+		2,      // Attribute Type code (AS Path)
+		12,     // Length
+		2,      // Type = AS_SEQUENCE
+		2,      // Path Segment Length
+		59, 65, // AS15169
+		12, 248, // AS3320
+		1,      // Type = AS_SET
+		2,      // Path Segment Length
+		59, 65, // AS15169
+		12, 248, // AS3320
+
+		0,              // Attribute flags
+		3,              // Attribute Type code (Next Hop)
+		4,              // Length
+		10, 11, 12, 13, // Next Hop
+
+		0,          // Attribute flags
+		4,          // Attribute Type code (MED)
+		4,          // Length
+		0, 0, 1, 0, // MED 256
+
+		0,          // Attribute flags
+		5,          // Attribute Type code (Local Pref)
+		4,          // Length
+		0, 0, 1, 0, // Local Pref 256
+
+		// NLRI
+		24,
+		192, 168, 0,
+
+		// #####################################################################
+		// Peer Down Notification
+		// #####################################################################
+		// Common Header
+		3,           // Version
+		0, 0, 0, 49, // Message Length
+		2, // Msg Type = Peer Down Notification
+
+		// Per Peer Header
+		0,                      // Peer Type
+		0,                      // Peer Flags
+		0, 0, 0, 0, 0, 0, 0, 0, // Peer Distinguisher
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 40, // 10.20.30.40 peer address
+		0, 0, 0, 100, // Peer AS
+		0, 0, 0, 255, // Peer BGP ID
+		0, 0, 0, 0, // Timestamp s
+		0, 0, 0, 0, // Timestamp µs
+
+		4, // Reason
+	})
+
+	time.Sleep(time.Millisecond * 50)
+	assert.Empty(t, r.neighbors)
+
+	time.Sleep(time.Millisecond * 50)
+
+	count := rib4.RouteCount()
+	if count != 0 {
+		t.Errorf("Unexpected route count. Expected: 0 Got: %d", count)
+	}
+}
+
+func TestBMPFullRunWithTerminationMessage(t *testing.T) {
+	addr := net.IP{10, 20, 30, 40}
+	port := uint16(12346)
+
+	rib4 := locRIB.New()
+	rib6 := locRIB.New()
+
+	r := newRouter(addr, port, rib4, rib6)
+	con := biotesting.NewMockConn()
+
+	go r.serve(con)
+
+	con.Write([]byte{
+		// #####################################################################
+		// Initiation Message
+		// #####################################################################
+		// Common Header
+		3,
+		0, 0, 0, 23,
+		4,
+		0, 1, // sysDescr
+		0, 4, // Length
+		42, 42, 42, 42, // AAAA
+		0, 2, //sysName
+		0, 5, // Length
+		43, 43, 43, 43, 43, // BBBBB
+
+		// #####################################################################
+		// Peer UP Notification
+		// #####################################################################
+		// Common Header
+		3,            // Version
+		0, 0, 0, 126, // Message Length
+		3, // Msg Type = Peer Up Notification
+		// Per Peer Header
+		0,                      // Peer Type
+		0,                      // Peer Flags
+		0, 0, 0, 0, 0, 0, 0, 0, // Peer Distinguisher
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 40, // 10.20.30.40 peer address
+		0, 0, 0, 100, // Peer AS
+		0, 0, 0, 255, // Peer BGP ID
+		0, 0, 0, 0, // Timestamp s
+		0, 0, 0, 0, // Timestamp µs
+		// Peer Up Notification
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 41, // 10.20.30.41 local address
+		0, 123, // Local Port
+		0, 234, // Remote Port
+		// Sent OPEN message
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 29, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 200, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 1, // BGP Identifier
+		0, // Opt param length
+		// Received OPEN message
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 29, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 100, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 255, // BGP Identifier
+		0, // Opt param length
+
+		// #####################################################################
+		// Route Monitoring Message #1
+		// #####################################################################
+		// Common Header
+		3,            // Version
+		0, 0, 0, 116, // Message Length
+		0, // Msg Type = Route Monitoring Message
+
+		// Per Peer Header
+		0,                      // Peer Type
+		0,                      // Peer Flags
+		0, 0, 0, 0, 0, 0, 0, 0, // Peer Distinguisher
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 30, 40, // 10.20.30.40 peer address
+		0, 0, 0, 100, // Peer AS
+		0, 0, 0, 255, // Peer BGP ID
+		0, 0, 0, 0, // Timestamp s
+		0, 0, 0, 0, // Timestamp µs
+
+		// BGP Update
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 68, // Length
+		2, // Update
+
+		0, 0, // Withdrawn Routes Length
+		0, 41, // Total Path Attribute Length
+
+		255,  // Attribute flags
+		1,    // Attribute Type code (ORIGIN)
+		0, 1, // Length
+		2, // INCOMPLETE
+
+		0,      // Attribute flags
+		2,      // Attribute Type code (AS Path)
+		12,     // Length
+		2,      // Type = AS_SEQUENCE
+		2,      // Path Segment Length
+		59, 65, // AS15169
+		12, 248, // AS3320
+		1,      // Type = AS_SET
+		2,      // Path Segment Length
+		59, 65, // AS15169
+		12, 248, // AS3320
+
+		0,              // Attribute flags
+		3,              // Attribute Type code (Next Hop)
+		4,              // Length
+		10, 11, 12, 13, // Next Hop
+
+		0,          // Attribute flags
+		4,          // Attribute Type code (MED)
+		4,          // Length
+		0, 0, 1, 0, // MED 256
+
+		0,          // Attribute flags
+		5,          // Attribute Type code (Local Pref)
+		4,          // Length
+		0, 0, 1, 0, // Local Pref 256
+
+		// NLRI
+		24,
+		192, 168, 0,
+
+		// #####################################################################
+		// Termination Message
+		// #####################################################################
+		// Common Header
+		3,           // Version
+		0, 0, 0, 12, // Message Length
+		5, // Msg Type = Termination Message
+
+		// TLV
+		0, 0, 0, 2,
+		42, 42,
+	})
+
+	time.Sleep(time.Millisecond * 50)
+	assert.Empty(t, r.neighbors)
+
+	time.Sleep(time.Millisecond * 50)
+
+	count := rib4.RouteCount()
+	if count != 0 {
+		t.Errorf("Unexpected route count. Expected: 0 Got: %d", count)
+	}
+}
diff --git a/protocols/bgp/server/fsm_address_family.go b/protocols/bgp/server/fsm_address_family.go
index 01ee06b7533385f4358c0823298e936f407cb49b..ac1ace92cb7894b4fdf179497e6375a74598b0a7 100644
--- a/protocols/bgp/server/fsm_address_family.go
+++ b/protocols/bgp/server/fsm_address_family.go
@@ -71,6 +71,16 @@ func (f *fsmAddressFamily) bmpInit() {
 	f.adjRIBIn.Register(f.rib)
 }
 
+func (f *fsmAddressFamily) bmpDispose() {
+	f.rib.GetContributingASNs().Remove(f.fsm.peer.localASN)
+
+	f.adjRIBIn.(*adjRIBIn.AdjRIBIn).Flush()
+
+	f.adjRIBIn.Unregister(f.rib)
+
+	f.adjRIBIn = nil
+}
+
 func (f *fsmAddressFamily) dispose() {
 	if !f.initialized {
 		return
diff --git a/protocols/bmp/packet/decode.go b/protocols/bmp/packet/decode.go
index d7989e28bb5955a294b195962d06c980cd0b645b..a76f6b7853e221126b77512039d9fc5296469496 100644
--- a/protocols/bmp/packet/decode.go
+++ b/protocols/bmp/packet/decode.go
@@ -61,7 +61,7 @@ func Decode(msg []byte) (Msg, error) {
 
 		return sr, nil
 	case PeerDownNotificationType:
-		pd, err := decodePeerUpNotification(buf, ch)
+		pd, err := decodePeerDownNotification(buf, ch)
 		if err != nil {
 			return nil, fmt.Errorf("Unable to decode peer down notification: %v", err)
 		}
diff --git a/protocols/bmp/packet/peer_down.go b/protocols/bmp/packet/peer_down.go
index cdb72ffe33f72dc77e4c7373b6041a467bbbf836..7b0303043f489f93ce4c1ed4cc2610cbb87fa9e2 100644
--- a/protocols/bmp/packet/peer_down.go
+++ b/protocols/bmp/packet/peer_down.go
@@ -57,7 +57,7 @@ func decodePeerDownNotification(buf *bytes.Buffer, ch *CommonHeader) (*PeerDownN
 
 	err = decoder.Decode(buf, fields)
 	if err != nil {
-		return nil, err
+		return nil, fmt.Errorf("Unable to read Data: %v", err)
 	}
 
 	return p, nil
diff --git a/routingtable/adjRIBIn/adj_rib_in.go b/routingtable/adjRIBIn/adj_rib_in.go
index 631f1d197cabc926056f186e21e1b6cd5d719afd..5bf7862334ece9b649baf5c75e42eff4936689f9 100644
--- a/routingtable/adjRIBIn/adj_rib_in.go
+++ b/routingtable/adjRIBIn/adj_rib_in.go
@@ -37,6 +37,19 @@ func New(exportFilter *filter.Filter, contributingASNs *routingtable.Contributin
 	return a
 }
 
+// Flush drops all routes from the AdjRIBIn
+func (a *AdjRIBIn) Flush() {
+	a.mu.Lock()
+	defer a.mu.Unlock()
+
+	routes := a.rt.Dump()
+	for _, route := range routes {
+		for _, path := range route.Paths() {
+			a.removePath(route.Prefix(), path)
+		}
+	}
+}
+
 // UpdateNewClient sends current state to a new client
 func (a *AdjRIBIn) UpdateNewClient(client routingtable.RouteTableClient) error {
 	a.mu.RLock()
@@ -124,6 +137,11 @@ func (a *AdjRIBIn) RemovePath(pfx net.Prefix, p *route.Path) bool {
 	a.mu.Lock()
 	defer a.mu.Unlock()
 
+	return a.removePath(pfx, p)
+}
+
+// removePath removes the path for prefix `pfx`
+func (a *AdjRIBIn) removePath(pfx net.Prefix, p *route.Path) bool {
 	r := a.rt.Get(pfx)
 	if r == nil {
 		return false