diff --git a/protocols/bmp/packet/decode_test.go b/protocols/bmp/packet/decode_test.go new file mode 100644 index 0000000000000000000000000000000000000000..b3419725826e141b6225838f30d9e7d91296a2ba --- /dev/null +++ b/protocols/bmp/packet/decode_test.go @@ -0,0 +1,453 @@ +package packet + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDecode(t *testing.T) { + tests := []struct { + name string + input []byte + wantFail bool + expected Msg + }{ + { + name: "incomplete common header", + input: []byte{1, 2}, + wantFail: true, + }, + { + name: "Invalid version", + input: []byte{0, 0, 0, 0, 6, 5}, + wantFail: true, + }, + { + name: "Route monitoring ok", + input: []byte{ + 3, 0, 0, 0, 6 + 38 + 4, 0, + + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + + 1, 2, 3, 4, + }, + wantFail: false, + expected: &RouteMonitoringMsg{ + CommonHeader: &CommonHeader{ + Version: 3, + MsgLength: 6 + 38 + 4, + MsgType: 0, + }, + PerPeerHeader: &PerPeerHeader{ + PeerType: 1, + PeerFlags: 2, + PeerDistinguisher: 3, + PeerAddress: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + PeerAS: 51324, + PeerBGPID: 123, + Timestamp: 100, + TimestampMicroSeconds: 200, + }, + BGPUpdate: []byte{1, 2, 3, 4}, + }, + }, + { + name: "Route monitoring nok", + input: []byte{ + 3, 0, 0, 0, 6 + 38 + 4, 0, + + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + + 1, 2, + }, + wantFail: true, + }, + { + name: "Statistic report ok", + input: []byte{ + 3, 0, 0, 0, 6 + 9 + 38, 1, + + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + + 0, 0, 0, 1, + 0, 1, 0, 1, 1, + }, + wantFail: false, + expected: &StatsReport{ + CommonHeader: &CommonHeader{ + Version: 3, + MsgLength: 6 + 9 + 38, + MsgType: 1, + }, + PerPeerHeader: &PerPeerHeader{ + PeerType: 1, + PeerFlags: 2, + PeerDistinguisher: 3, + PeerAddress: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + PeerAS: 51324, + PeerBGPID: 123, + Timestamp: 100, + TimestampMicroSeconds: 200, + }, + StatsCount: 1, + Stats: []*InformationTLV{ + { + InformationType: 1, + InformationLength: 1, + Information: []byte{1}, + }, + }, + }, + }, + { + name: "Statistic report nok", + input: []byte{ + 3, 0, 0, 0, 6 + 9 + 38, 1, + + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + }, + wantFail: true, + }, + { + name: "peer down ok", + input: []byte{ + 3, 0, 0, 0, 6 + 9 + 38, 1, + + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + + 0, 0, 0, 1, + 0, 1, 0, 1, 1, + }, + wantFail: false, + expected: &StatsReport{ + CommonHeader: &CommonHeader{ + Version: 3, + MsgLength: 6 + 9 + 38, + MsgType: 1, + }, + PerPeerHeader: &PerPeerHeader{ + PeerType: 1, + PeerFlags: 2, + PeerDistinguisher: 3, + PeerAddress: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + PeerAS: 51324, + PeerBGPID: 123, + Timestamp: 100, + TimestampMicroSeconds: 200, + }, + StatsCount: 1, + Stats: []*InformationTLV{ + { + InformationType: 1, + InformationLength: 1, + Information: []byte{1}, + }, + }, + }, + }, + { + name: "peer down nok", + input: []byte{ + 3, 0, 0, 0, 6 + 9 + 38, 1, + + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + + 0, 0, 0, 1, + 0, 1, 0, 1, + }, + wantFail: true, + }, + { + name: "peer up ok", + input: []byte{ + 3, 0, 0, 0, 54, 3, + + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 100, + 0, 200, + + // OPEN Sent + 4, // Version + 1, 0, // ASN + 2, 0, // Hold Time + 100, 110, 120, 130, // BGP Identifier + 5, // Opt Parm Len + 1, 2, 3, 4, 5, + + // OPEN Recv + 4, // Version + 1, 0, // ASN + 2, 0, // Hold Time + 100, 110, 120, 130, // BGP Identifier + 0, // Opt Parm Len + + 120, 140, 160, // Information + }, + wantFail: false, + expected: &PeerUpNotification{ + CommonHeader: &CommonHeader{ + Version: 3, + MsgLength: 54, + MsgType: 3, + }, + PerPeerHeader: &PerPeerHeader{ + PeerType: 1, + PeerFlags: 2, + PeerDistinguisher: 3, + PeerAddress: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + PeerAS: 51324, + PeerBGPID: 123, + Timestamp: 100, + TimestampMicroSeconds: 200, + }, + LocalAddress: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + LocalPort: 100, + RemotePort: 200, + SentOpenMsg: []byte{ + 4, // Version + 1, 0, // ASN + 2, 0, // Hold Time + 100, 110, 120, 130, // BGP Identifier + 5, // Opt Parm Len + 1, 2, 3, 4, 5, + }, + ReceivedOpenMsg: []byte{ + // OPEN Recv + 4, // Version + 1, 0, // ASN + 2, 0, // Hold Time + 100, 110, 120, 130, // BGP Identifier + 0, // Opt Parm Len + }, + Information: []byte{ + 120, 140, 160, // Information + }, + }, + }, + { + name: "peer up nok", + input: []byte{ + 3, 0, 0, 0, 54, 3, + + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 100, + 0, 200, + + // OPEN Sent + 4, // Version + 1, 0, // ASN + 2, 0, // Hold Time + 100, 110, 120, 130, // BGP Identifier + 5, // Opt Parm Len + 1, 2, 3, 4, 5, + + // OPEN Recv + 4, // Version + 1, + }, + wantFail: true, + }, + { + name: "initiation message ok", + input: []byte{ + 3, 0, 0, 0, 11, 4, + + 0, 1, 0, 1, 5, + }, + wantFail: false, + expected: &InitiationMessage{ + CommonHeader: &CommonHeader{ + Version: 3, + MsgLength: 11, + MsgType: 4, + }, + TLVs: []*InformationTLV{ + { + InformationType: 1, + InformationLength: 1, + Information: []byte{5}, + }, + }, + }, + }, + { + name: "initiation message nok", + input: []byte{ + 3, 0, 0, 0, + }, + wantFail: true, + }, + { + name: "termination message ok", + input: []byte{ + 3, 0, 0, 0, 11, 5, + + 0, 1, 0, 1, 5, + }, + wantFail: false, + expected: &TerminationMessage{ + CommonHeader: &CommonHeader{ + Version: 3, + MsgLength: 11, + MsgType: 5, + }, + TLVs: []*InformationTLV{ + { + InformationType: 1, + InformationLength: 1, + Information: []byte{5}, + }, + }, + }, + }, + { + name: "termination message nok", + input: []byte{ + 3, 0, 0, 0, 11, 5, + + 0, 1, 0, + }, + wantFail: true, + }, + { + name: "route mirror message ok", + input: []byte{ + 3, 0, 0, 0, 49, 6, + + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, 0, 123, + 0, 0, 0, 100, + 0, 0, 0, 200, + + 0, 1, 0, 1, 5, + }, + wantFail: false, + expected: &RouteMirroringMsg{ + CommonHeader: &CommonHeader{ + Version: 3, + MsgLength: 49, + MsgType: 6, + }, + PerPeerHeader: &PerPeerHeader{ + PeerType: 1, + PeerFlags: 2, + PeerDistinguisher: 3, + PeerAddress: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + PeerAS: 51324, + PeerBGPID: 123, + Timestamp: 100, + TimestampMicroSeconds: 200, + }, + TLVs: []*InformationTLV{ + { + InformationType: 1, + InformationLength: 1, + Information: []byte{5}, + }, + }, + }, + }, + { + name: "route mirror message nok", + input: []byte{ + 3, 0, 0, 0, 49, 6, + + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 0, 0, 200, 124, + 0, 0, + }, + wantFail: true, + }, + { + name: "invalid msg type", + input: []byte{ + 3, 0, 0, 0, 49, 7, + }, + wantFail: true, + }, + } + + for _, test := range tests { + m, err := Decode(test.input) + if err != nil { + if test.wantFail { + continue + } + + t.Errorf("Unexpected failure for test %q: %v", test.name, err) + continue + } + + if test.wantFail { + t.Errorf("Unexpected success for test %q", test.name) + continue + } + + assert.Equalf(t, test.expected, m, "Test %q", test.name) + } +}