diff --git a/protocols/bgp/server/bmp_router_test.go b/protocols/bgp/server/bmp_router_test.go index a8887deecb1d1e88b0b341434c65580f136a4377..3c74e6b82b358c964b5ed58f6a2a8d3b28944de9 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 332736728f876b75ae12b7e5d00f5326c4094e52..b239ace82259ccdb7c64c2867380827b0acbb481 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 086ec90ede76cff15810e30e02971391a02476be..d40b672d482827cf09ad4cbbbdd013b591f8b552 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() } }