From 8a38d3b5fa499b407308e083c2e6cf42c59256d5 Mon Sep 17 00:00:00 2001
From: Oliver Herms <oliver.herms@exaring.de>
Date: Wed, 24 Oct 2018 17:55:56 +0200
Subject: [PATCH] Moar tests

---
 protocols/bgp/server/bmp_router_test.go | 2073 ++++++++++++++++++++
 protocols/bgp/server/bmp_server.go      |    1 +
 protocols/bgp/server/bmp_server_test.go | 2297 +++--------------------
 3 files changed, 2324 insertions(+), 2047 deletions(-)

diff --git a/protocols/bgp/server/bmp_router_test.go b/protocols/bgp/server/bmp_router_test.go
index a8887dee..3c74e6b8 100644
--- a/protocols/bgp/server/bmp_router_test.go
+++ b/protocols/bgp/server/bmp_router_test.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"net"
 	"testing"
+	"time"
 
 	bnet "github.com/bio-routing/bio-rd/net"
 	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
@@ -671,3 +672,2075 @@ func TestRegisterClients(t *testing.T) {
 	assert.Equal(t, int64(1), n.fsm.ipv4Unicast.adjRIBIn.RouteCount())
 	assert.Equal(t, int64(1), n.fsm.ipv6Unicast.adjRIBIn.RouteCount())
 }
+
+func TestIntegrationPeerUpRouteMonitor(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)
+	conA, conB := net.Pipe()
+
+	go r.serve(conB)
+
+	// Peer Up Notification
+	_, err := conA.Write([]byte{
+		// 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
+
+		// 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
+
+		// 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,
+	})
+
+	if err != nil {
+		panic("write failed")
+	}
+
+	time.Sleep(time.Millisecond * 50)
+	assert.NotEmpty(t, r.neighbors)
+
+	time.Sleep(time.Millisecond * 50)
+
+	count := rib4.RouteCount()
+	if count != 1 {
+		t.Errorf("Unexpected route count. Expected: 1 Got: %d", count)
+	}
+
+	conA.Close()
+}
+
+func TestIntegrationPeerUpRouteMonitorIPv6IPv4(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)
+	conA, conB := net.Pipe()
+
+	go r.serve(conB)
+
+	// Peer Up Notification
+	_, err := conA.Write([]byte{
+		// Common Header
+		3,            // Version
+		0, 0, 0, 142, // 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, 37, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 200, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 1, // BGP Identifier
+		8, // Opt param length
+		2, 6,
+		1, 4, // MP BGP
+		0, 2, // IPv6
+		0, 1, // Unicast
+
+		// Received OPEN message
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 37, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 100, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 255, // BGP Identifier
+		8, // Opt param length
+		2, 6,
+		1, 4, // MP BGP
+		0, 2, // IPv6
+		0, 1, // Unicast
+
+		// SECOND MESSAGE:
+
+		// Common Header
+		3,            // Version
+		0, 0, 0, 138, // 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, 90, // Length
+		2, // Update
+
+		0, 0, // Withdrawn Routes Length
+		0, 67, // Total Path Attribute Length
+
+		255,
+		14,    // MP REACH NLRI
+		0, 22, // Length
+		0, 2, // IPv6
+		1,  // Unicast
+		16, // IPv6 Next Hop
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0, // Reserved
+		0, // Pfxlen /0
+
+		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
+
+		// THIRD MESSAGE
+		// Common Header
+		3,            // Version
+		0, 0, 0, 113, // 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, 65, // 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
+
+		0, // /0
+	})
+
+	if err != nil {
+		panic("write failed")
+	}
+
+	time.Sleep(time.Millisecond * 50)
+	assert.NotEmpty(t, r.neighbors)
+
+	time.Sleep(time.Millisecond * 50)
+
+	count := rib6.RouteCount()
+	if count != 1 {
+		t.Errorf("Unexpected IPv6 route count. Expected: 1 Got: %d", count)
+	}
+
+	count = rib4.RouteCount()
+	if count != 1 {
+		t.Errorf("Unexpected IPv4 route count. Expected: 1 Got: %d", count)
+	}
+
+	conA.Close()
+}
+
+func TestIntegrationPeerUpRouteMonitorIPv4IPv6(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)
+	conA, conB := net.Pipe()
+
+	go r.serve(conB)
+
+	// Peer Up Notification
+	_, err := conA.Write([]byte{
+		// Common Header
+		3,            // Version
+		0, 0, 0, 142, // 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, 37, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 200, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 1, // BGP Identifier
+		8, // Opt param length
+		2, 6,
+		1, 4, // MP BGP
+		0, 2, // IPv6
+		0, 1, // Unicast
+
+		// Received OPEN message
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 37, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 100, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 255, // BGP Identifier
+		8, // Opt param length
+		2, 6,
+		1, 4, // MP BGP
+		0, 2, // IPv6
+		0, 1, // Unicast
+
+		// SECOND MESSAGE:
+
+		// Common Header
+		3,            // Version
+		0, 0, 0, 113, // 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, 65, // 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
+
+		0, // /0
+
+		// THIRD MESSAGE
+
+		// Common Header
+		3,            // Version
+		0, 0, 0, 138, // 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, 90, // Length
+		2, // Update
+
+		0, 0, // Withdrawn Routes Length
+		0, 67, // Total Path Attribute Length
+
+		255,
+		14,    // MP REACH NLRI
+		0, 22, // Length
+		0, 2, // IPv6
+		1,  // Unicast
+		16, // IPv6 Next Hop
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0, // Reserved
+		0, // Pfxlen /0
+
+		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
+	})
+
+	if err != nil {
+		panic("write failed")
+	}
+
+	time.Sleep(time.Millisecond * 50)
+	assert.NotEmpty(t, r.neighbors)
+
+	time.Sleep(time.Millisecond * 50)
+
+	count := rib6.RouteCount()
+	if count != 1 {
+		t.Errorf("Unexpected IPv6 route count. Expected: 1 Got: %d", count)
+	}
+
+	count = rib4.RouteCount()
+	if count != 1 {
+		t.Errorf("Unexpected IPv4 route count. Expected: 1 Got: %d", count)
+	}
+
+	conA.Close()
+}
+
+func TestIntegrationPeerUpRouteMonitorIPv6(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)
+	conA, conB := net.Pipe()
+
+	go r.serve(conB)
+
+	// Peer Up Notification
+	_, err := conA.Write([]byte{
+		// Common Header
+		3,            // Version
+		0, 0, 0, 142, // 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, 37, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 200, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 1, // BGP Identifier
+		8, // Opt param length
+		2, 6,
+		1, 4, // MP BGP
+		0, 2, // IPv6
+		0, 1, // Unicast
+
+		// Received OPEN message
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 37, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 100, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 255, // BGP Identifier
+		8, // Opt param length
+		2, 6,
+		1, 4, // MP BGP
+		0, 2, // IPv6
+		0, 1, // Unicast
+
+		// SECOND MESSAGE:
+
+		// Common Header
+		3,            // Version
+		0, 0, 0, 138, // 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, 90, // Length
+		2, // Update
+
+		0, 0, // Withdrawn Routes Length
+		0, 67, // Total Path Attribute Length
+
+		255,
+		14,    // MP REACH NLRI
+		0, 22, // Length
+		0, 2, // IPv6
+		1,  // Unicast
+		16, // IPv6 Next Hop
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0, // Reserved
+		0, // Pfxlen /0
+
+		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
+	})
+
+	if err != nil {
+		panic("write failed")
+	}
+
+	time.Sleep(time.Millisecond * 50)
+	assert.NotEmpty(t, r.neighbors)
+
+	time.Sleep(time.Millisecond * 50)
+
+	count := rib6.RouteCount()
+	if count != 1 {
+		t.Errorf("Unexpected IPv6 route count. Expected: 1 Got: %d", count)
+	}
+
+	count = rib4.RouteCount()
+	if count != 0 {
+		t.Errorf("Unexpected IPv4 route count. Expected: 0 Got: %d", count)
+	}
+
+	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)
+	}
+}
+
+func TestIntegrationPeerUpRouteMonitorIPv6WithClientAtEnd(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)
+	conA, conB := net.Pipe()
+
+	go r.serve(conB)
+
+	// Peer Up Notification
+	_, err := conA.Write([]byte{
+		// Common Header
+		3,            // Version
+		0, 0, 0, 142, // 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, 37, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 200, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 1, // BGP Identifier
+		8, // Opt param length
+		2, 6,
+		1, 4, // MP BGP
+		0, 2, // IPv6
+		0, 1, // Unicast
+
+		// Received OPEN message
+		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		0, 37, // Length
+		1,      // Open message type
+		4,      // BGP Version
+		0, 100, // AS
+		0, 180, // Hold Time
+		1, 0, 0, 255, // BGP Identifier
+		8, // Opt param length
+		2, 6,
+		1, 4, // MP BGP
+		0, 2, // IPv6
+		0, 1, // Unicast
+
+		// SECOND MESSAGE:
+
+		// Common Header
+		3,            // Version
+		0, 0, 0, 138, // 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, 90, // Length
+		2, // Update
+
+		0, 0, // Withdrawn Routes Length
+		0, 67, // Total Path Attribute Length
+
+		255,
+		14,    // MP REACH NLRI
+		0, 22, // Length
+		0, 2, // IPv6
+		1,  // Unicast
+		16, // IPv6 Next Hop
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0, // Reserved
+		0, // Pfxlen /0
+
+		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
+	})
+
+	if err != nil {
+		panic("write failed")
+	}
+
+	time.Sleep(time.Millisecond * 50)
+	assert.NotEmpty(t, r.neighbors)
+
+	time.Sleep(time.Millisecond * 50)
+
+	count := rib6.RouteCount()
+	if count != 1 {
+		t.Errorf("Unexpected IPv6 route count. Expected: 1 Got: %d", count)
+	}
+
+	count = rib4.RouteCount()
+	if count != 0 {
+		t.Errorf("Unexpected IPv4 route count. Expected: 0 Got: %d", count)
+	}
+
+	client6 := locRIB.New()
+	r.subscribeRIBs(client6, packet.IPv6AFI)
+
+	count = client6.RouteCount()
+	if count != 1 {
+		t.Errorf("Unexpected IPv6 route count. Expected: 1 Got: %d", count)
+	}
+
+	conA.Close()
+}
+
+func TestIntegrationPeerUpRouteMonitorIPv6WithClientBeforeBMPPeer(t *testing.T) {
+	tests := []struct {
+		name               string
+		afi                uint8
+		unregister         bool
+		doubleSubscribe    bool
+		doubleUnsubscribe  bool
+		input              []byte
+		expectedRouteCount int
+	}{
+		{
+			name:       "IPv4 without unregister",
+			afi:        packet.IPv4AFI,
+			unregister: false,
+			input: []byte{
+				// Common Header
+				3,            // Version
+				0, 0, 0, 142, // 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, 37, // Length
+				1,      // Open message type
+				4,      // BGP Version
+				0, 200, // AS
+				0, 180, // Hold Time
+				1, 0, 0, 1, // BGP Identifier
+				8, // Opt param length
+				2, 6,
+				1, 4, // MP BGP
+				0, 2, // IPv6
+				0, 1, // Unicast
+
+				// Received OPEN message
+				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+				0, 37, // Length
+				1,      // Open message type
+				4,      // BGP Version
+				0, 100, // AS
+				0, 180, // Hold Time
+				1, 0, 0, 255, // BGP Identifier
+				8, // Opt param length
+				2, 6,
+				1, 4, // MP BGP
+				0, 2, // IPv6
+				0, 1, // Unicast
+
+				// 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
+
+				// 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,
+			},
+			expectedRouteCount: 1,
+		},
+		{
+			name:       "IPv4 with unregister",
+			afi:        packet.IPv4AFI,
+			unregister: true,
+			input: []byte{
+				// Common Header
+				3,            // Version
+				0, 0, 0, 142, // 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, 37, // Length
+				1,      // Open message type
+				4,      // BGP Version
+				0, 200, // AS
+				0, 180, // Hold Time
+				1, 0, 0, 1, // BGP Identifier
+				8, // Opt param length
+				2, 6,
+				1, 4, // MP BGP
+				0, 2, // IPv6
+				0, 1, // Unicast
+
+				// Received OPEN message
+				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+				0, 37, // Length
+				1,      // Open message type
+				4,      // BGP Version
+				0, 100, // AS
+				0, 180, // Hold Time
+				1, 0, 0, 255, // BGP Identifier
+				8, // Opt param length
+				2, 6,
+				1, 4, // MP BGP
+				0, 2, // IPv6
+				0, 1, // Unicast
+
+				// 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
+
+				// 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,
+			},
+			expectedRouteCount: 1,
+		},
+		{
+			name:              "IPv4 with double unregister",
+			afi:               packet.IPv4AFI,
+			doubleUnsubscribe: true,
+			unregister:        true,
+			input: []byte{
+				// Common Header
+				3,            // Version
+				0, 0, 0, 142, // 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, 37, // Length
+				1,      // Open message type
+				4,      // BGP Version
+				0, 200, // AS
+				0, 180, // Hold Time
+				1, 0, 0, 1, // BGP Identifier
+				8, // Opt param length
+				2, 6,
+				1, 4, // MP BGP
+				0, 2, // IPv6
+				0, 1, // Unicast
+
+				// Received OPEN message
+				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+				0, 37, // Length
+				1,      // Open message type
+				4,      // BGP Version
+				0, 100, // AS
+				0, 180, // Hold Time
+				1, 0, 0, 255, // BGP Identifier
+				8, // Opt param length
+				2, 6,
+				1, 4, // MP BGP
+				0, 2, // IPv6
+				0, 1, // Unicast
+
+				// 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
+
+				// 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,
+			},
+			expectedRouteCount: 1,
+		},
+		{
+			name:            "IPv4 with double register",
+			afi:             packet.IPv4AFI,
+			doubleSubscribe: true,
+			unregister:      true,
+			input: []byte{
+				// Common Header
+				3,            // Version
+				0, 0, 0, 142, // 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, 37, // Length
+				1,      // Open message type
+				4,      // BGP Version
+				0, 200, // AS
+				0, 180, // Hold Time
+				1, 0, 0, 1, // BGP Identifier
+				8, // Opt param length
+				2, 6,
+				1, 4, // MP BGP
+				0, 2, // IPv6
+				0, 1, // Unicast
+
+				// Received OPEN message
+				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+				0, 37, // Length
+				1,      // Open message type
+				4,      // BGP Version
+				0, 100, // AS
+				0, 180, // Hold Time
+				1, 0, 0, 255, // BGP Identifier
+				8, // Opt param length
+				2, 6,
+				1, 4, // MP BGP
+				0, 2, // IPv6
+				0, 1, // Unicast
+
+				// 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
+
+				// 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,
+			},
+			expectedRouteCount: 1,
+		},
+		{
+			name:       "IPv6 without unregister",
+			afi:        packet.IPv6AFI,
+			unregister: false,
+			input: []byte{
+				// Common Header
+				3,            // Version
+				0, 0, 0, 142, // 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, 37, // Length
+				1,      // Open message type
+				4,      // BGP Version
+				0, 200, // AS
+				0, 180, // Hold Time
+				1, 0, 0, 1, // BGP Identifier
+				8, // Opt param length
+				2, 6,
+				1, 4, // MP BGP
+				0, 2, // IPv6
+				0, 1, // Unicast
+
+				// Received OPEN message
+				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+				0, 37, // Length
+				1,      // Open message type
+				4,      // BGP Version
+				0, 100, // AS
+				0, 180, // Hold Time
+				1, 0, 0, 255, // BGP Identifier
+				8, // Opt param length
+				2, 6,
+				1, 4, // MP BGP
+				0, 2, // IPv6
+				0, 1, // Unicast
+
+				// SECOND MESSAGE:
+
+				// Common Header
+				3,            // Version
+				0, 0, 0, 138, // 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, 90, // Length
+				2, // Update
+
+				0, 0, // Withdrawn Routes Length
+				0, 67, // Total Path Attribute Length
+
+				255,
+				14,    // MP REACH NLRI
+				0, 22, // Length
+				0, 2, // IPv6
+				1,  // Unicast
+				16, // IPv6 Next Hop
+				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				0, // Reserved
+				0, // Pfxlen /0
+
+				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
+			},
+			expectedRouteCount: 1,
+		},
+	}
+
+	for _, test := range tests {
+		addr := net.IP{10, 20, 30, 40}
+		port := uint16(12346)
+
+		rib4 := locRIB.New()
+		rib6 := locRIB.New()
+
+		r := newRouter(addr, port, rib4, rib6)
+		conA, conB := net.Pipe()
+
+		client := locRIB.New()
+		r.subscribeRIBs(client, test.afi)
+		if test.doubleSubscribe {
+			r.subscribeRIBs(client, test.afi)
+		}
+
+		if test.unregister {
+			r.unsubscribeRIBs(client, test.afi)
+			if test.doubleUnsubscribe {
+				r.unsubscribeRIBs(client, test.afi)
+			}
+		}
+
+		go r.serve(conB)
+
+		_, err := conA.Write(test.input)
+
+		if err != nil {
+			panic("write failed")
+		}
+
+		time.Sleep(time.Millisecond * 50)
+
+		expectedCount := int64(1)
+		if test.unregister {
+			expectedCount = 0
+		}
+
+		count := client.RouteCount()
+		if count != expectedCount {
+			t.Errorf("Unexpected route count for test %q. Expected: %d Got: %d", test.name, expectedCount, count)
+		}
+
+		conA.Close()
+	}
+}
diff --git a/protocols/bgp/server/bmp_server.go b/protocols/bgp/server/bmp_server.go
index 33273672..b239ace8 100644
--- a/protocols/bgp/server/bmp_server.go
+++ b/protocols/bgp/server/bmp_server.go
@@ -83,6 +83,7 @@ func (b *BMPServer) UnsubscribeRIBs(client routingtable.RouteTableClient, rtr ne
 		return
 	}
 
+	delete(b.ribClients[rtrStr], ac)
 	b.routers[rtrStr].unsubscribeRIBs(client, afi)
 }
 
diff --git a/protocols/bgp/server/bmp_server_test.go b/protocols/bgp/server/bmp_server_test.go
index 086ec90e..d40b672d 100644
--- a/protocols/bgp/server/bmp_server_test.go
+++ b/protocols/bgp/server/bmp_server_test.go
@@ -3,11 +3,8 @@ package server
 import (
 	"net"
 	"testing"
-	"time"
 
 	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
-	"github.com/bio-routing/bio-rd/routingtable/locRIB"
-	biotesting "github.com/bio-routing/bio-rd/testing"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -19,2074 +16,280 @@ func TestNewServer(t *testing.T) {
 	}, s)
 }
 
-func TestIntegrationPeerUpRouteMonitor(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)
-	conA, conB := net.Pipe()
-
-	go r.serve(conB)
-
-	// Peer Up Notification
-	_, err := conA.Write([]byte{
-		// 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
-
-		// 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
-
-		// 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,
-	})
-
-	if err != nil {
-		panic("write failed")
-	}
-
-	time.Sleep(time.Millisecond * 50)
-	assert.NotEmpty(t, r.neighbors)
-
-	time.Sleep(time.Millisecond * 50)
-
-	count := rib4.RouteCount()
-	if count != 1 {
-		t.Errorf("Unexpected route count. Expected: 1 Got: %d", count)
-	}
-
-	conA.Close()
-}
-
-func TestIntegrationPeerUpRouteMonitorIPv6IPv4(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)
-	conA, conB := net.Pipe()
-
-	go r.serve(conB)
-
-	// Peer Up Notification
-	_, err := conA.Write([]byte{
-		// Common Header
-		3,            // Version
-		0, 0, 0, 142, // 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, 37, // Length
-		1,      // Open message type
-		4,      // BGP Version
-		0, 200, // AS
-		0, 180, // Hold Time
-		1, 0, 0, 1, // BGP Identifier
-		8, // Opt param length
-		2, 6,
-		1, 4, // MP BGP
-		0, 2, // IPv6
-		0, 1, // Unicast
-
-		// Received OPEN message
-		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-		0, 37, // Length
-		1,      // Open message type
-		4,      // BGP Version
-		0, 100, // AS
-		0, 180, // Hold Time
-		1, 0, 0, 255, // BGP Identifier
-		8, // Opt param length
-		2, 6,
-		1, 4, // MP BGP
-		0, 2, // IPv6
-		0, 1, // Unicast
-
-		// SECOND MESSAGE:
-
-		// Common Header
-		3,            // Version
-		0, 0, 0, 138, // 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, 90, // Length
-		2, // Update
-
-		0, 0, // Withdrawn Routes Length
-		0, 67, // Total Path Attribute Length
-
-		255,
-		14,    // MP REACH NLRI
-		0, 22, // Length
-		0, 2, // IPv6
-		1,  // Unicast
-		16, // IPv6 Next Hop
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0, // Reserved
-		0, // Pfxlen /0
-
-		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
-
-		// THIRD MESSAGE
-		// Common Header
-		3,            // Version
-		0, 0, 0, 113, // 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, 65, // 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
-
-		0, // /0
-	})
-
-	if err != nil {
-		panic("write failed")
-	}
-
-	time.Sleep(time.Millisecond * 50)
-	assert.NotEmpty(t, r.neighbors)
-
-	time.Sleep(time.Millisecond * 50)
-
-	count := rib6.RouteCount()
-	if count != 1 {
-		t.Errorf("Unexpected IPv6 route count. Expected: 1 Got: %d", count)
-	}
-
-	count = rib4.RouteCount()
-	if count != 1 {
-		t.Errorf("Unexpected IPv4 route count. Expected: 1 Got: %d", count)
-	}
-
-	conA.Close()
-}
-
-func TestIntegrationPeerUpRouteMonitorIPv4IPv6(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)
-	conA, conB := net.Pipe()
-
-	go r.serve(conB)
-
-	// Peer Up Notification
-	_, err := conA.Write([]byte{
-		// Common Header
-		3,            // Version
-		0, 0, 0, 142, // 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, 37, // Length
-		1,      // Open message type
-		4,      // BGP Version
-		0, 200, // AS
-		0, 180, // Hold Time
-		1, 0, 0, 1, // BGP Identifier
-		8, // Opt param length
-		2, 6,
-		1, 4, // MP BGP
-		0, 2, // IPv6
-		0, 1, // Unicast
-
-		// Received OPEN message
-		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-		0, 37, // Length
-		1,      // Open message type
-		4,      // BGP Version
-		0, 100, // AS
-		0, 180, // Hold Time
-		1, 0, 0, 255, // BGP Identifier
-		8, // Opt param length
-		2, 6,
-		1, 4, // MP BGP
-		0, 2, // IPv6
-		0, 1, // Unicast
-
-		// SECOND MESSAGE:
-
-		// Common Header
-		3,            // Version
-		0, 0, 0, 113, // 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, 65, // 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
-
-		0, // /0
-
-		// THIRD MESSAGE
-
-		// Common Header
-		3,            // Version
-		0, 0, 0, 138, // 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, 90, // Length
-		2, // Update
-
-		0, 0, // Withdrawn Routes Length
-		0, 67, // Total Path Attribute Length
-
-		255,
-		14,    // MP REACH NLRI
-		0, 22, // Length
-		0, 2, // IPv6
-		1,  // Unicast
-		16, // IPv6 Next Hop
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0, // Reserved
-		0, // Pfxlen /0
-
-		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
-	})
-
-	if err != nil {
-		panic("write failed")
-	}
-
-	time.Sleep(time.Millisecond * 50)
-	assert.NotEmpty(t, r.neighbors)
-
-	time.Sleep(time.Millisecond * 50)
-
-	count := rib6.RouteCount()
-	if count != 1 {
-		t.Errorf("Unexpected IPv6 route count. Expected: 1 Got: %d", count)
-	}
-
-	count = rib4.RouteCount()
-	if count != 1 {
-		t.Errorf("Unexpected IPv4 route count. Expected: 1 Got: %d", count)
-	}
-
-	conA.Close()
-}
-
-func TestIntegrationPeerUpRouteMonitorIPv6(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)
-	conA, conB := net.Pipe()
-
-	go r.serve(conB)
-
-	// Peer Up Notification
-	_, err := conA.Write([]byte{
-		// Common Header
-		3,            // Version
-		0, 0, 0, 142, // 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, 37, // Length
-		1,      // Open message type
-		4,      // BGP Version
-		0, 200, // AS
-		0, 180, // Hold Time
-		1, 0, 0, 1, // BGP Identifier
-		8, // Opt param length
-		2, 6,
-		1, 4, // MP BGP
-		0, 2, // IPv6
-		0, 1, // Unicast
-
-		// Received OPEN message
-		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-		0, 37, // Length
-		1,      // Open message type
-		4,      // BGP Version
-		0, 100, // AS
-		0, 180, // Hold Time
-		1, 0, 0, 255, // BGP Identifier
-		8, // Opt param length
-		2, 6,
-		1, 4, // MP BGP
-		0, 2, // IPv6
-		0, 1, // Unicast
-
-		// SECOND MESSAGE:
-
-		// Common Header
-		3,            // Version
-		0, 0, 0, 138, // 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, 90, // Length
-		2, // Update
-
-		0, 0, // Withdrawn Routes Length
-		0, 67, // Total Path Attribute Length
-
-		255,
-		14,    // MP REACH NLRI
-		0, 22, // Length
-		0, 2, // IPv6
-		1,  // Unicast
-		16, // IPv6 Next Hop
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0, // Reserved
-		0, // Pfxlen /0
-
-		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
-	})
-
-	if err != nil {
-		panic("write failed")
-	}
-
-	time.Sleep(time.Millisecond * 50)
-	assert.NotEmpty(t, r.neighbors)
-
-	time.Sleep(time.Millisecond * 50)
-
-	count := rib6.RouteCount()
-	if count != 1 {
-		t.Errorf("Unexpected IPv6 route count. Expected: 1 Got: %d", count)
-	}
-
-	count = rib4.RouteCount()
-	if count != 0 {
-		t.Errorf("Unexpected IPv4 route count. Expected: 0 Got: %d", count)
-	}
-
-	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)
-	}
-}
-
-func TestIntegrationPeerUpRouteMonitorIPv6WithClientAtEnd(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)
-	conA, conB := net.Pipe()
-
-	go r.serve(conB)
-
-	// Peer Up Notification
-	_, err := conA.Write([]byte{
-		// Common Header
-		3,            // Version
-		0, 0, 0, 142, // 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, 37, // Length
-		1,      // Open message type
-		4,      // BGP Version
-		0, 200, // AS
-		0, 180, // Hold Time
-		1, 0, 0, 1, // BGP Identifier
-		8, // Opt param length
-		2, 6,
-		1, 4, // MP BGP
-		0, 2, // IPv6
-		0, 1, // Unicast
-
-		// Received OPEN message
-		255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-		0, 37, // Length
-		1,      // Open message type
-		4,      // BGP Version
-		0, 100, // AS
-		0, 180, // Hold Time
-		1, 0, 0, 255, // BGP Identifier
-		8, // Opt param length
-		2, 6,
-		1, 4, // MP BGP
-		0, 2, // IPv6
-		0, 1, // Unicast
-
-		// SECOND MESSAGE:
-
-		// Common Header
-		3,            // Version
-		0, 0, 0, 138, // 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, 90, // Length
-		2, // Update
-
-		0, 0, // Withdrawn Routes Length
-		0, 67, // Total Path Attribute Length
-
-		255,
-		14,    // MP REACH NLRI
-		0, 22, // Length
-		0, 2, // IPv6
-		1,  // Unicast
-		16, // IPv6 Next Hop
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0, // Reserved
-		0, // Pfxlen /0
-
-		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
-	})
-
-	if err != nil {
-		panic("write failed")
-	}
-
-	time.Sleep(time.Millisecond * 50)
-	assert.NotEmpty(t, r.neighbors)
-
-	time.Sleep(time.Millisecond * 50)
-
-	count := rib6.RouteCount()
-	if count != 1 {
-		t.Errorf("Unexpected IPv6 route count. Expected: 1 Got: %d", count)
-	}
-
-	count = rib4.RouteCount()
-	if count != 0 {
-		t.Errorf("Unexpected IPv4 route count. Expected: 0 Got: %d", count)
-	}
-
-	client6 := locRIB.New()
-	r.subscribeRIBs(client6, packet.IPv6AFI)
-
-	count = client6.RouteCount()
-	if count != 1 {
-		t.Errorf("Unexpected IPv6 route count. Expected: 1 Got: %d", count)
-	}
-
-	conA.Close()
-}
-
-func TestIntegrationPeerUpRouteMonitorIPv6WithClientBeforeBMPPeer(t *testing.T) {
+func TestSubscribeRIBs(t *testing.T) {
 	tests := []struct {
-		name               string
-		afi                uint8
-		unregister         bool
-		doubleSubscribe    bool
-		doubleUnsubscribe  bool
-		input              []byte
-		expectedRouteCount int
+		name     string
+		srv      *BMPServer
+		expected *BMPServer
 	}{
 		{
-			name:       "IPv4 without unregister",
-			afi:        packet.IPv4AFI,
-			unregister: false,
-			input: []byte{
-				// Common Header
-				3,            // Version
-				0, 0, 0, 142, // 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, 37, // Length
-				1,      // Open message type
-				4,      // BGP Version
-				0, 200, // AS
-				0, 180, // Hold Time
-				1, 0, 0, 1, // BGP Identifier
-				8, // Opt param length
-				2, 6,
-				1, 4, // MP BGP
-				0, 2, // IPv6
-				0, 1, // Unicast
-
-				// Received OPEN message
-				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-				0, 37, // Length
-				1,      // Open message type
-				4,      // BGP Version
-				0, 100, // AS
-				0, 180, // Hold Time
-				1, 0, 0, 255, // BGP Identifier
-				8, // Opt param length
-				2, 6,
-				1, 4, // MP BGP
-				0, 2, // IPv6
-				0, 1, // Unicast
-
-				// 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
-
-				// 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,
+			name: "Test without routers with clients",
+			srv: &BMPServer{
+				routers: make(map[string]*router),
+				ribClients: map[string]map[afiClient]struct{}{
+					"20.30.40.50": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+				},
+			},
+			expected: &BMPServer{
+				routers: make(map[string]*router),
+				ribClients: map[string]map[afiClient]struct{}{
+					"20.30.40.50": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+					"10.20.30.40": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+				},
 			},
-			expectedRouteCount: 1,
 		},
 		{
-			name:       "IPv4 with unregister",
-			afi:        packet.IPv4AFI,
-			unregister: true,
-			input: []byte{
-				// Common Header
-				3,            // Version
-				0, 0, 0, 142, // 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, 37, // Length
-				1,      // Open message type
-				4,      // BGP Version
-				0, 200, // AS
-				0, 180, // Hold Time
-				1, 0, 0, 1, // BGP Identifier
-				8, // Opt param length
-				2, 6,
-				1, 4, // MP BGP
-				0, 2, // IPv6
-				0, 1, // Unicast
-
-				// Received OPEN message
-				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-				0, 37, // Length
-				1,      // Open message type
-				4,      // BGP Version
-				0, 100, // AS
-				0, 180, // Hold Time
-				1, 0, 0, 255, // BGP Identifier
-				8, // Opt param length
-				2, 6,
-				1, 4, // MP BGP
-				0, 2, // IPv6
-				0, 1, // Unicast
-
-				// 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
-
-				// 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,
+			name: "Test with routers no clients",
+			srv: &BMPServer{
+				routers: map[string]*router{
+					"10.20.30.40": &router{
+						ribClients: make(map[afiClient]struct{}),
+					},
+				},
+				ribClients: map[string]map[afiClient]struct{}{},
+			},
+			expected: &BMPServer{
+				routers: map[string]*router{
+					"10.20.30.40": &router{
+						ribClients: map[afiClient]struct{}{
+							afiClient{
+								afi:    packet.IPv4AFI,
+								client: nil,
+							}: struct{}{},
+						},
+					},
+				},
+				ribClients: map[string]map[afiClient]struct{}{
+					"10.20.30.40": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+				},
 			},
-			expectedRouteCount: 1,
 		},
-		{
-			name:              "IPv4 with double unregister",
-			afi:               packet.IPv4AFI,
-			doubleUnsubscribe: true,
-			unregister:        true,
-			input: []byte{
-				// Common Header
-				3,            // Version
-				0, 0, 0, 142, // 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, 37, // Length
-				1,      // Open message type
-				4,      // BGP Version
-				0, 200, // AS
-				0, 180, // Hold Time
-				1, 0, 0, 1, // BGP Identifier
-				8, // Opt param length
-				2, 6,
-				1, 4, // MP BGP
-				0, 2, // IPv6
-				0, 1, // Unicast
-
-				// Received OPEN message
-				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-				0, 37, // Length
-				1,      // Open message type
-				4,      // BGP Version
-				0, 100, // AS
-				0, 180, // Hold Time
-				1, 0, 0, 255, // BGP Identifier
-				8, // Opt param length
-				2, 6,
-				1, 4, // MP BGP
-				0, 2, // IPv6
-				0, 1, // Unicast
-
-				// 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
-
-				// 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
+	for _, test := range tests {
+		test.srv.SubscribeRIBs(nil, net.IP{10, 20, 30, 40}, packet.IPv4AFI)
 
-				0,          // Attribute flags
-				4,          // Attribute Type code (MED)
-				4,          // Length
-				0, 0, 1, 0, // MED 256
+		assert.Equalf(t, test.expected, test.srv, "Test %q", test.name)
 
-				0,          // Attribute flags
-				5,          // Attribute Type code (Local Pref)
-				4,          // Length
-				0, 0, 1, 0, // Local Pref 256
+	}
+}
 
-				// NLRI
-				24,
-				192, 168, 0,
+func TestUnsubscribeRIBs(t *testing.T) {
+	tests := []struct {
+		name     string
+		srv      *BMPServer
+		expected *BMPServer
+	}{
+		{
+			name: "Unsubscribe existing from router",
+			srv: &BMPServer{
+				routers: map[string]*router{
+					"10.20.30.40": &router{
+						ribClients: map[afiClient]struct{}{
+							afiClient{
+								afi:    packet.IPv4AFI,
+								client: nil,
+							}: struct{}{},
+						},
+					},
+					"20.30.40.50": &router{
+						ribClients: map[afiClient]struct{}{
+							afiClient{
+								afi:    packet.IPv4AFI,
+								client: nil,
+							}: struct{}{},
+						},
+					},
+				},
+				ribClients: map[string]map[afiClient]struct{}{
+					"20.30.40.50": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+					"10.20.30.40": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+				},
+			},
+			expected: &BMPServer{
+				routers: map[string]*router{
+					"10.20.30.40": &router{
+						ribClients: map[afiClient]struct{}{},
+					},
+					"20.30.40.50": &router{
+						ribClients: map[afiClient]struct{}{
+							afiClient{
+								afi:    packet.IPv4AFI,
+								client: nil,
+							}: struct{}{},
+						},
+					},
+				},
+				ribClients: map[string]map[afiClient]struct{}{
+					"20.30.40.50": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+					"10.20.30.40": map[afiClient]struct{}{
+					},
+				},
 			},
-			expectedRouteCount: 1,
 		},
 		{
-			name:            "IPv4 with double register",
-			afi:             packet.IPv4AFI,
-			doubleSubscribe: true,
-			unregister:      true,
-			input: []byte{
-				// Common Header
-				3,            // Version
-				0, 0, 0, 142, // 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, 37, // Length
-				1,      // Open message type
-				4,      // BGP Version
-				0, 200, // AS
-				0, 180, // Hold Time
-				1, 0, 0, 1, // BGP Identifier
-				8, // Opt param length
-				2, 6,
-				1, 4, // MP BGP
-				0, 2, // IPv6
-				0, 1, // Unicast
-
-				// Received OPEN message
-				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-				0, 37, // Length
-				1,      // Open message type
-				4,      // BGP Version
-				0, 100, // AS
-				0, 180, // Hold Time
-				1, 0, 0, 255, // BGP Identifier
-				8, // Opt param length
-				2, 6,
-				1, 4, // MP BGP
-				0, 2, // IPv6
-				0, 1, // Unicast
-
-				// 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
-
-				// 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,
+			name: "Unsubscribe existing from non-router",
+			srv: &BMPServer{
+				routers: map[string]*router{
+					"10.20.30.60": &router{
+						ribClients: map[afiClient]struct{}{
+							afiClient{
+								afi:    packet.IPv4AFI,
+								client: nil,
+							}: struct{}{},
+						},
+					},
+					"20.30.40.50": &router{
+						ribClients: map[afiClient]struct{}{
+							afiClient{
+								afi:    packet.IPv4AFI,
+								client: nil,
+							}: struct{}{},
+						},
+					},
+				},
+				ribClients: map[string]map[afiClient]struct{}{
+					"20.30.40.50": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+					"10.20.30.60": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+				},
+			},
+			expected: &BMPServer{
+				routers: map[string]*router{
+					"10.20.30.60": &router{
+						ribClients: map[afiClient]struct{}{
+							afiClient{
+								afi:    packet.IPv4AFI,
+								client: nil,
+							}: struct{}{},
+						},
+					},
+					"20.30.40.50": &router{
+						ribClients: map[afiClient]struct{}{
+							afiClient{
+								afi:    packet.IPv4AFI,
+								client: nil,
+							}: struct{}{},
+						},
+					},
+				},
+				ribClients: map[string]map[afiClient]struct{}{
+					"20.30.40.50": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+					"10.20.30.60": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+				},
 			},
-			expectedRouteCount: 1,
 		},
 		{
-			name:       "IPv6 without unregister",
-			afi:        packet.IPv6AFI,
-			unregister: false,
-			input: []byte{
-				// Common Header
-				3,            // Version
-				0, 0, 0, 142, // 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, 37, // Length
-				1,      // Open message type
-				4,      // BGP Version
-				0, 200, // AS
-				0, 180, // Hold Time
-				1, 0, 0, 1, // BGP Identifier
-				8, // Opt param length
-				2, 6,
-				1, 4, // MP BGP
-				0, 2, // IPv6
-				0, 1, // Unicast
-
-				// Received OPEN message
-				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-				0, 37, // Length
-				1,      // Open message type
-				4,      // BGP Version
-				0, 100, // AS
-				0, 180, // Hold Time
-				1, 0, 0, 255, // BGP Identifier
-				8, // Opt param length
-				2, 6,
-				1, 4, // MP BGP
-				0, 2, // IPv6
-				0, 1, // Unicast
-
-				// SECOND MESSAGE:
-
-				// Common Header
-				3,            // Version
-				0, 0, 0, 138, // 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, 90, // Length
-				2, // Update
-
-				0, 0, // Withdrawn Routes Length
-				0, 67, // Total Path Attribute Length
-
-				255,
-				14,    // MP REACH NLRI
-				0, 22, // Length
-				0, 2, // IPv6
-				1,  // Unicast
-				16, // IPv6 Next Hop
-				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-				0, // Reserved
-				0, // Pfxlen /0
-
-				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
+			name: "Unsubscribe existing from non-existing client",
+			srv: &BMPServer{
+				routers: map[string]*router{
+					"10.20.30.40": &router{
+						ribClients: map[afiClient]struct{}{},
+					},
+					"20.30.40.50": &router{
+						ribClients: map[afiClient]struct{}{
+							afiClient{
+								afi:    packet.IPv4AFI,
+								client: nil,
+							}: struct{}{},
+						},
+					},
+				},
+				ribClients: map[string]map[afiClient]struct{}{
+					"20.30.40.40": map[afiClient]struct{}{},
+					"10.20.30.60": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+				},
+			},
+			expected: &BMPServer{
+				routers: map[string]*router{
+					"10.20.30.40": &router{
+						ribClients: map[afiClient]struct{}{},
+					},
+					"20.30.40.50": &router{
+						ribClients: map[afiClient]struct{}{
+							afiClient{
+								afi:    packet.IPv4AFI,
+								client: nil,
+							}: struct{}{},
+						},
+					},
+				},
+				ribClients: map[string]map[afiClient]struct{}{
+					"20.30.40.40": map[afiClient]struct{}{},
+					"10.20.30.60": map[afiClient]struct{}{
+						afiClient{
+							afi:    packet.IPv4AFI,
+							client: nil,
+						}: struct{}{},
+					},
+				},
 			},
-			expectedRouteCount: 1,
 		},
 	}
 
 	for _, test := range tests {
-		addr := net.IP{10, 20, 30, 40}
-		port := uint16(12346)
-
-		rib4 := locRIB.New()
-		rib6 := locRIB.New()
-
-		r := newRouter(addr, port, rib4, rib6)
-		conA, conB := net.Pipe()
-
-		client := locRIB.New()
-		r.subscribeRIBs(client, test.afi)
-		if test.doubleSubscribe {
-			r.subscribeRIBs(client, test.afi)
-		}
-
-		if test.unregister {
-			r.unsubscribeRIBs(client, test.afi)
-			if test.doubleUnsubscribe {
-				r.unsubscribeRIBs(client, test.afi)
-			}
-		}
-
-		go r.serve(conB)
-
-		_, err := conA.Write(test.input)
-
-		if err != nil {
-			panic("write failed")
-		}
-
-		time.Sleep(time.Millisecond * 50)
-
-		expectedCount := int64(1)
-		if test.unregister {
-			expectedCount = 0
-		}
+		test.srv.UnsubscribeRIBs(nil, net.IP{10, 20, 30, 40}, packet.IPv4AFI)
 
-		count := client.RouteCount()
-		if count != expectedCount {
-			t.Errorf("Unexpected route count for test %q. Expected: %d Got: %d", test.name, expectedCount, count)
-		}
+		assert.Equalf(t, test.expected, test.srv, "Test %q", test.name)
 
-		conA.Close()
 	}
 }
-- 
GitLab