diff --git a/protocols/bmp/packet/per_peer_header.go b/protocols/bmp/packet/per_peer_header.go index 87231c86920a6729ce72a5de9cbb6a4f4f12e122..f17a92014a496f68d6f1af280f854c6b434ac01a 100644 --- a/protocols/bmp/packet/per_peer_header.go +++ b/protocols/bmp/packet/per_peer_header.go @@ -7,6 +7,11 @@ import ( "github.com/bio-routing/tflow2/convert" ) +const ( + // PerPeerHeaderLen is the length of a per peer header + PerPeerHeaderLen = 38 +) + // PerPeerHeader represents a BMP per peer header type PerPeerHeader struct { PeerType uint8 diff --git a/protocols/bmp/packet/route_mirroring.go b/protocols/bmp/packet/route_mirroring.go deleted file mode 100644 index 9c40969f7215a143587237b30d213bdd01db4a74..0000000000000000000000000000000000000000 --- a/protocols/bmp/packet/route_mirroring.go +++ /dev/null @@ -1 +0,0 @@ -package packet diff --git a/protocols/bmp/packet/route_monitoring.go b/protocols/bmp/packet/route_monitoring.go index 9c40969f7215a143587237b30d213bdd01db4a74..d76aa453fd9ecb5869f4f6e1436db4db83029eee 100644 --- a/protocols/bmp/packet/route_monitoring.go +++ b/protocols/bmp/packet/route_monitoring.go @@ -1 +1,46 @@ package packet + +import ( + "bytes" + "fmt" + + "github.com/bio-routing/bio-rd/util/decoder" +) + +// RouteMonitoringMsg represents a Route Monitoring Message +type RouteMonitoringMsg struct { + CommonHeader *CommonHeader + PerPeerHeader *PerPeerHeader + BGPUpdate []byte +} + +// MsgType returns the type of this message +func (rm *RouteMonitoringMsg) MsgType() uint8 { + return rm.CommonHeader.MsgType +} + +func decodeRouteMonitoringMsg(buf *bytes.Buffer, ch *CommonHeader) (*RouteMonitoringMsg, error) { + rm := &RouteMonitoringMsg{ + CommonHeader: ch, + } + + pph, err := decodePerPeerHeader(buf) + if err != nil { + return nil, fmt.Errorf("Unable to decode per peer header: %v", err) + } + + rm.PerPeerHeader = pph + + rm.BGPUpdate = make([]byte, ch.MsgLength-CommonHeaderLen-PerPeerHeaderLen) + + fields := []interface{}{ + &rm.BGPUpdate, + } + + err = decoder.Decode(buf, fields) + if err != nil { + return nil, err + } + + return rm, nil +} diff --git a/protocols/bmp/packet/route_monitoring_test.go b/protocols/bmp/packet/route_monitoring_test.go new file mode 100644 index 0000000000000000000000000000000000000000..c6cee1f7f1aea3e48bcf57177fcc0f34b2aaf1d8 --- /dev/null +++ b/protocols/bmp/packet/route_monitoring_test.go @@ -0,0 +1,89 @@ +package packet + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDecodeRouteMonitoringMsg(t *testing.T) { + tests := []struct { + name string + input []byte + ch *CommonHeader + wantFail bool + expected *RouteMonitoringMsg + }{ + { + name: "Full", + input: []byte{ + 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, + + 100, 110, 120, + }, + ch: &CommonHeader{ + MsgLength: CommonHeaderLen + PerPeerHeaderLen + 3, + }, + wantFail: false, + expected: &RouteMonitoringMsg{ + CommonHeader: &CommonHeader{ + MsgLength: CommonHeaderLen + PerPeerHeaderLen + 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, + }, + BGPUpdate: []byte{ + 100, 110, 120, + }, + }, + }, + { + name: "Incomplete per peer header", + input: []byte{ + 1, + 2, + 0, 0, 0, 3, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + }, + ch: &CommonHeader{ + MsgLength: CommonHeaderLen + PerPeerHeaderLen + 3, + }, + wantFail: true, + }, + } + + for _, test := range tests { + buf := bytes.NewBuffer(test.input) + r, err := decodeRouteMonitoringMsg(buf, test.ch) + 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, r, "Test %q", test.name) + } +}