From 7ee75ef7ce61d4c6252443c046207978d90534cc Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm <max@sdn.clinic> Date: Tue, 3 Jul 2018 16:47:40 +0200 Subject: [PATCH] Add lot's of tests for RR path attribute decoding and serialization. Signed-off-by: Maximilian Wilhelm <max@sdn.clinic> --- protocols/bgp/packet/path_attributes_test.go | 293 +++++++++++++++++++ 1 file changed, 293 insertions(+) diff --git a/protocols/bgp/packet/path_attributes_test.go b/protocols/bgp/packet/path_attributes_test.go index 486f19d0..040cdfbf 100644 --- a/protocols/bgp/packet/path_attributes_test.go +++ b/protocols/bgp/packet/path_attributes_test.go @@ -172,6 +172,80 @@ func TestDecodePathAttr(t *testing.T) { }, wantFail: true, }, + { + name: "Missing value OriginatorID", + input: []byte{ + 0, + OriginatorIDAttr, + 4, + }, + wantFail: true, + }, + { + name: "Valid OriginatorID", + input: []byte{ + 128, // Attr. Flags + OriginatorIDAttr, // Attr. Type Code + 4, // Attr. Length + 1, 2, 3, 4, + }, + wantFail: false, + expected: &PathAttribute{ + Length: 4, + Optional: true, + Transitive: false, + Partial: false, + ExtendedLength: false, + TypeCode: OriginatorIDAttr, + Value: bnet.IPv4FromOctets(1, 2, 3, 4).ToUint32(), + }, + }, + { + name: "one valid ClusterID", + input: []byte{ + 128, // Attr. Flags + ClusterListAttr, // Attr. Type Code + 4, // Attr. Length + 1, 1, 1, 1, + }, + wantFail: false, + expected: &PathAttribute{ + TypeCode: ClusterListAttr, + Optional: true, + Length: 4, + Value: []uint32{ + bnet.IPv4FromOctets(1, 1, 1, 1).ToUint32(), + }, + }, + }, + { + name: "two valid ClusterIDs", + input: []byte{ + setOptional(uint8(0)), // Attr. Flags + ClusterListAttr, // Attr. Type Code + 8, // Attr. Length + 1, 2, 3, 4, 8, 8, 8, 8, // 1.2.3.4, 8.8.8.8 + }, + wantFail: false, + expected: &PathAttribute{ + TypeCode: ClusterListAttr, + Optional: true, + Length: 8, + Value: []uint32{ + bnet.IPv4FromOctets(1, 2, 3, 4).ToUint32(), bnet.IPv4FromOctets(8, 8, 8, 8).ToUint32(), + }, + }, + }, + { + name: "one and a half ClusterID", + input: []byte{ + setOptional(uint8(0)), // Attr. Flags + ClusterListAttr, // Attr. Type Code + 8, // Attr. Length + 1, 2, 3, 4, 8, 8, // 1.2.3.4, 8.8. + }, + wantFail: true, + }, } for _, test := range tests { @@ -746,6 +820,85 @@ func TestDecodeCommunity(t *testing.T) { } } +func TestDecodeClusterList(t *testing.T) { + tests := []struct { + name string + input []byte + wantFail bool + explicitLength uint16 + expected *PathAttribute + }{ + { + name: "Empty input", + input: []byte{}, + wantFail: false, + expected: &PathAttribute{ + Length: 0, + Value: []uint32{}, + }, + }, + { + name: "one valid ClusterID", + input: []byte{ + 1, 1, 1, 1, + }, + wantFail: false, + expected: &PathAttribute{ + Length: 4, + Value: []uint32{ + bnet.IPv4FromOctets(1, 1, 1, 1).ToUint32(), + }, + }, + }, + { + name: "two valid ClusterIDs", + input: []byte{ + 1, 2, 3, 4, 8, 8, 8, 8, // 1.2.3.4, 8.8.8.8 + }, + wantFail: false, + expected: &PathAttribute{ + Length: 8, + Value: []uint32{ + bnet.IPv4FromOctets(1, 2, 3, 4).ToUint32(), bnet.IPv4FromOctets(8, 8, 8, 8).ToUint32(), + }, + }, + }, + { + name: "one and a half ClusterID", + input: []byte{ + 1, 2, 3, 4, 8, 8, // 1.2.3.4, 8.8. + }, + wantFail: true, + }, + } + + for _, test := range tests { + l := uint16(len(test.input)) + if test.explicitLength != 0 { + l = test.explicitLength + } + pa := &PathAttribute{ + Length: l, + } + err := pa.decodeClusterList(bytes.NewBuffer(test.input)) + + if test.wantFail { + if err != nil { + continue + } + t.Errorf("Expected error did not happen for test %q", test.name) + continue + } + + if err != nil { + t.Errorf("Unexpected failure for test %q: %v", test.name, err) + continue + } + + assert.Equal(t, test.expected, pa) + } +} + func TestDecodeMultiProtocolReachNLRI(t *testing.T) { tests := []struct { name string @@ -1479,6 +1632,106 @@ func TestSerializeCommunities(t *testing.T) { } } +func TestSerializeOriginatorID(t *testing.T) { + tests := []struct { + name string + input *PathAttribute + expected []byte + expectedLen uint8 + }{ + { + name: "Valid OriginatorID", + input: &PathAttribute{ + TypeCode: OriginatorIDAttr, + Value: bnet.IPv4FromOctets(1, 1, 1, 1).ToUint32(), + }, + expected: []byte{ + setOptional(uint8(0)), // Attribute flags + OriginatorIDAttr, // Type + 4, // Length + 1, 1, 1, 1, // ClusterID (1.1.1.1) + }, + expectedLen: 7, + }, + } + + for _, test := range tests { + t.Run(test.name, func(te *testing.T) { + buf := bytes.NewBuffer(nil) + n := test.input.serializeOriginatorID(buf) + if n != test.expectedLen { + t.Errorf("Unexpected length for test %q: %d", test.name, n) + } + + assert.Equal(t, test.expected, buf.Bytes()) + }) + } +} + +func TestSerializeClusterList(t *testing.T) { + tests := []struct { + name string + input *PathAttribute + expected []byte + expectedLen uint8 + }{ + { + name: "Empty list of CluserIDs", + input: &PathAttribute{ + TypeCode: ClusterListAttr, + Value: []uint32{}, + }, + expected: []byte{}, + expectedLen: 0, + }, + { + name: "One ClusterID", + input: &PathAttribute{ + TypeCode: ClusterListAttr, + Value: []uint32{ + bnet.IPv4FromOctets(1, 1, 1, 1).ToUint32(), + }, + }, + expected: []byte{ + setOptional(uint8(0)), // Attribute flags + ClusterListAttr, // Type + 4, // Length + 1, 1, 1, 1, // ClusterID (1.1.1.1) + }, + expectedLen: 4, + }, + { + name: "Two ClusterIDs", + input: &PathAttribute{ + TypeCode: ClusterListAttr, + Value: []uint32{ + bnet.IPv4FromOctets(1, 1, 1, 1).ToUint32(), + bnet.IPv4FromOctets(192, 168, 23, 42).ToUint32(), + }, + }, + expected: []byte{ + setOptional(uint8(0)), // Attribute flags + ClusterListAttr, // Type + 8, // Length + 1, 1, 1, 1, 192, 168, 23, 42, // ClusterID (1.1.1.1) + }, + expectedLen: 8, + }, + } + + for _, test := range tests { + t.Run(test.name, func(te *testing.T) { + buf := bytes.NewBuffer([]byte{}) + n := test.input.serializeClusterList(buf) + if n != test.expectedLen { + t.Fatalf("Unexpected length for test %q: %d", test.name, n) + } + + assert.Equal(t, test.expected, buf.Bytes()) + }) + } +} + func TestSerializeUnknownAttribute(t *testing.T) { tests := []struct { name string @@ -1724,6 +1977,46 @@ func TestSerialize(t *testing.T) { 22, 185, 65, 240, // 185.65.240.0/22 }, }, + { + name: "Reflected NLRI", + msg: &BGPUpdate{ + NLRI: &NLRI{ + IP: strAddr("100.110.128.0"), + Pfxlen: 17, + }, + PathAttributes: &PathAttribute{ + TypeCode: OriginatorIDAttr, + Value: bnet.IPv4FromOctets(9, 8, 7, 6).ToUint32(), + Next: &PathAttribute{ + TypeCode: ClusterListAttr, + Value: []uint32{ + bnet.IPv4FromOctets(1, 2, 3, 4).ToUint32(), + }, + }, + }, + }, + expected: []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0, 41, // Length + 2, // Msg Type + 0, 0, // Withdrawn Routes Length + + 0, 14, // Total Path Attribute Length + // OriginatorID + 128, // Attr. Flags (Opt.) + 9, // Attr. Type Code + 4, // Attr Length + 9, 8, 7, 6, // 9.8.7.6 + + // ClusterList + 128, // Attr Flags (Opt.) + 10, // Attr. Type Code + 4, + 1, 2, 3, 4, + + 17, 100, 110, 128, // NLRI + }, + }, } for _, test := range tests { -- GitLab