Skip to content
Snippets Groups Projects
path_attributes_test.go 37.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • 		expected    []byte
    		expectedLen uint8
    	}{
    		{
    			name: "Test #1",
    			input: &PathAttribute{
    				TypeCode: NextHopAttr,
    
    				Value:    bnet.IPv4FromOctets(100, 110, 120, 130),
    
    			expected:    []byte{64, 3, 4, 100, 110, 120, 130},
    
    			expectedLen: 7,
    		},
    	}
    
    	for _, test := range tests {
    		buf := bytes.NewBuffer(nil)
    		n := test.input.serializeNextHop(buf)
    		if n != test.expectedLen {
    			t.Errorf("Unexpected length for test %q: %d", test.name, n)
    			continue
    		}
    
    		assert.Equal(t, test.expected, buf.Bytes())
    	}
    }
    
    func TestSerializeMED(t *testing.T) {
    	tests := []struct {
    		name        string
    		input       *PathAttribute
    		expected    []byte
    		expectedLen uint8
    	}{
    		{
    			name: "Test #1",
    			input: &PathAttribute{
    				TypeCode: MEDAttr,
    				Value:    uint32(1000),
    			},
    			expected: []byte{
    				128,          // Attribute flags
    				4,            // Type
    				4,            // Length
    				0, 0, 3, 232, // Value = 1000
    			},
    			expectedLen: 7,
    		},
    	}
    
    	for _, test := range tests {
    		buf := bytes.NewBuffer(nil)
    		n := test.input.serializeMED(buf)
    		if n != test.expectedLen {
    			t.Errorf("Unexpected length for test %q: %d", test.name, n)
    			continue
    		}
    
    		assert.Equal(t, test.expected, buf.Bytes())
    	}
    }
    
    func TestSerializeLocalPref(t *testing.T) {
    	tests := []struct {
    		name        string
    		input       *PathAttribute
    		expected    []byte
    		expectedLen uint8
    	}{
    		{
    			name: "Test #1",
    			input: &PathAttribute{
    				TypeCode: LocalPrefAttr,
    				Value:    uint32(1000),
    			},
    			expected: []byte{
    				64,           // Attribute flags
    				5,            // Type
    				4,            // Length
    				0, 0, 3, 232, // Value = 1000
    			},
    			expectedLen: 7,
    		},
    	}
    
    	for _, test := range tests {
    		buf := bytes.NewBuffer(nil)
    		n := test.input.serializeLocalpref(buf)
    		if n != test.expectedLen {
    			t.Errorf("Unexpected length for test %q: %d", test.name, n)
    			continue
    		}
    
    		assert.Equal(t, test.expected, buf.Bytes())
    	}
    }
    
    func TestSerializeAtomicAggregate(t *testing.T) {
    	tests := []struct {
    		name        string
    		input       *PathAttribute
    		expected    []byte
    		expectedLen uint8
    	}{
    		{
    			name: "Test #1",
    			input: &PathAttribute{
    				TypeCode: AtomicAggrAttr,
    			},
    			expected: []byte{
    				64, // Attribute flags
    				6,  // Type
    				0,  // Length
    			},
    			expectedLen: 3,
    		},
    	}
    
    	for _, test := range tests {
    		buf := bytes.NewBuffer(nil)
    		n := test.input.serializeAtomicAggregate(buf)
    		if n != test.expectedLen {
    			t.Errorf("Unexpected length for test %q: %d", test.name, n)
    			continue
    		}
    
    		assert.Equal(t, test.expected, buf.Bytes())
    	}
    }
    
    func TestSerializeAggregator(t *testing.T) {
    	tests := []struct {
    		name        string
    		input       *PathAttribute
    		expected    []byte
    		expectedLen uint8
    	}{
    		{
    			name: "Test #1",
    			input: &PathAttribute{
    				TypeCode: AggregatorAttr,
    				Value:    uint16(174),
    			},
    			expected: []byte{
    				192,    // Attribute flags
    				7,      // Type
    				2,      // Length
    				0, 174, // Value = 174
    			},
    			expectedLen: 5,
    		},
    	}
    
    	for _, test := range tests {
    		buf := bytes.NewBuffer(nil)
    		n := test.input.serializeAggregator(buf)
    		if n != test.expectedLen {
    			t.Errorf("Unexpected length for test %q: %d", test.name, n)
    			continue
    		}
    
    		assert.Equal(t, test.expected, buf.Bytes())
    	}
    }
    
    func TestSerializeASPath(t *testing.T) {
    	tests := []struct {
    		name        string
    		input       *PathAttribute
    		expected    []byte
    		expectedLen uint8
    
    		use32BitASN bool
    
    	}{
    		{
    			name: "Test #1",
    			input: &PathAttribute{
    				TypeCode: ASPathAttr,
    
    Oliver Herms's avatar
    Oliver Herms committed
    				Value: types.ASPath{
    
    					{
    						Type: 2, // Sequence
    						ASNs: []uint32{
    							100, 200, 210,
    						},
    					},
    				},
    			},
    			expected: []byte{
    				64,     // Attribute flags
    				2,      // Type
    
    Oliver Herms's avatar
    Oliver Herms committed
    				8,      // Length
    
    				2,      // AS_SEQUENCE
    				3,      // ASN count
    				0, 100, // ASN 100
    				0, 200, // ASN 200
    				0, 210, // ASN 210
    			},
    			expectedLen: 10,
    		},
    
    		{
    			name: "32bit ASN",
    			input: &PathAttribute{
    				TypeCode: ASPathAttr,
    
    Oliver Herms's avatar
    Oliver Herms committed
    				Value: types.ASPath{
    
    					{
    						Type: 2, // Sequence
    						ASNs: []uint32{
    							100, 200, 210,
    						},
    					},
    				},
    			},
    			expected: []byte{
    				64,           // Attribute flags
    				2,            // Type
    				14,           // Length
    				2,            // AS_SEQUENCE
    				3,            // ASN count
    				0, 0, 0, 100, // ASN 100
    				0, 0, 0, 200, // ASN 200
    				0, 0, 0, 210, // ASN 210
    			},
    			expectedLen: 16,
    			use32BitASN: true,
    		},
    
    	t.Parallel()
    
    
    	for _, test := range tests {
    
    		t.Run(test.name, func(t *testing.T) {
    			buf := bytes.NewBuffer(nil)
    
    Oliver Herms's avatar
    Oliver Herms committed
    			opt := &types.Options{
    
    				Supports4OctetASN: test.use32BitASN,
    			}
    			n := test.input.serializeASPath(buf, opt)
    			if n != test.expectedLen {
    				t.Fatalf("Unexpected length for test %q: %d", test.name, n)
    			}
    
    			assert.Equal(t, test.expected, buf.Bytes())
    		})
    
    func TestSerializeLargeCommunities(t *testing.T) {
    	tests := []struct {
    		name        string
    		input       *PathAttribute
    		expected    []byte
    		expectedLen uint8
    	}{
    		{
    			name: "2 large communities",
    			input: &PathAttribute{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    				TypeCode: LargeCommunitiesAttr,
    
    Oliver Herms's avatar
    Oliver Herms committed
    				Value: []types.LargeCommunity{
    
    					{
    						GlobalAdministrator: 1,
    						DataPart1:           2,
    						DataPart2:           3,
    					},
    					{
    						GlobalAdministrator: 4,
    						DataPart1:           5,
    						DataPart2:           6,
    					},
    				},
    			},
    			expected: []byte{
    				0xe0,                                                                   // Attribute flags
    				32,                                                                     // Type
    				24,                                                                     // Length
    				0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, // Communities (1, 2, 3), (4, 5, 6)
    			},
    			expectedLen: 24,
    		},
    		{
    			name: "empty list of communities",
    			input: &PathAttribute{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    				TypeCode: LargeCommunitiesAttr,
    
    Oliver Herms's avatar
    Oliver Herms committed
    				Value:    []types.LargeCommunity{},
    
    			},
    			expected:    []byte{},
    			expectedLen: 0,
    		},
    	}
    
    	for _, test := range tests {
    		t.Run(test.name, func(te *testing.T) {
    			buf := bytes.NewBuffer([]byte{})
    			n := test.input.serializeLargeCommunities(buf)
    			if n != test.expectedLen {
    				t.Fatalf("Unexpected length for test %q: %d", test.name, n)
    			}
    
    			assert.Equal(t, test.expected, buf.Bytes())
    		})
    	}
    }
    
    
    func TestSerializeCommunities(t *testing.T) {
    	tests := []struct {
    		name        string
    		input       *PathAttribute
    		expected    []byte
    		expectedLen uint8
    	}{
    		{
    			name: "2 communities",
    			input: &PathAttribute{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    				TypeCode: LargeCommunitiesAttr,
    
    				Value: []uint32{
    					131080, 16778241,
    				},
    			},
    			expected: []byte{
    				0xe0,                   // Attribute flags
    				8,                      // Type
    				8,                      // Length
    				0, 2, 0, 8, 1, 0, 4, 1, // Communities (2,8), (256,1025)
    			},
    			expectedLen: 8,
    		},
    		{
    			name: "empty list of communities",
    			input: &PathAttribute{
    				TypeCode: CommunitiesAttr,
    				Value:    []uint32{},
    			},
    			expected:    []byte{},
    			expectedLen: 0,
    		},
    	}
    
    	for _, test := range tests {
    		t.Run(test.name, func(te *testing.T) {
    			buf := bytes.NewBuffer([]byte{})
    			n := test.input.serializeCommunities(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
    		input       *PathAttribute
    		expected    []byte
    
    	}{
    		{
    			name: "Arbritary attribute",
    			input: &PathAttribute{
    				TypeCode:   200,
    				Value:      []byte{1, 2, 3, 4},
    				Transitive: true,
    			},
    			expected: []byte{
    				64,         // Attribute flags
    				200,        // Type
    				4,          // Length
    				1, 2, 3, 4, // Payload
    			},
    			expectedLen: 6,
    		},
    
    		{
    			name: "Extended length",
    			input: &PathAttribute{
    				TypeCode:       200,
    				Value:          make([]byte, 256),
    				Transitive:     true,
    				ExtendedLength: true,
    			},
    			expected: []byte{
    				80,   // Attribute flags
    				200,  // Type
    				1, 0, // Length
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Payload
    			},
    			expectedLen: 258,
    		},
    
    	}
    
    	for _, test := range tests {
    		t.Run(test.name, func(t *testing.T) {
    			buf := bytes.NewBuffer(nil)
    			n := test.input.serializeUnknownAttribute(buf)
    
    			assert.Equal(t, test.expectedLen, n)
    			assert.Equal(t, test.expected, buf.Bytes())
    		})
    	}
    }
    
    
    func TestSerialize(t *testing.T) {
    	tests := []struct {
    		name     string
    		msg      *BGPUpdate
    		expected []byte
    		wantFail bool
    	}{
    		{
    			name: "Withdraw only",
    			msg: &BGPUpdate{
    				WithdrawnRoutes: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    					IP:     strAddr("100.110.120.0"),
    
    					Pfxlen: 24,
    				},
    			},
    			expected: []byte{
    				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    				0, 27, // Length
    				2,    // Msg Type
    				0, 4, // Withdrawn Routes Length
    				24, 100, 110, 120, // NLRI
    				0, 0, // Total Path Attribute Length
    			},
    		},
    		{
    			name: "NLRI only",
    			msg: &BGPUpdate{
    				NLRI: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    					IP:     strAddr("100.110.128.0"),
    
    					Pfxlen: 17,
    				},
    			},
    			expected: []byte{
    				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    				0, 27, // Length
    				2,    // Msg Type
    				0, 0, // Withdrawn Routes Length
    				0, 0, // Total Path Attribute Length
    				17, 100, 110, 128, // NLRI
    			},
    		},
    		{
    			name: "Path Attributes only",
    			msg: &BGPUpdate{
    				PathAttributes: &PathAttribute{
    					Optional:   true,
    					Transitive: true,
    					TypeCode:   OriginAttr,
    					Value:      uint8(0), // IGP
    				},
    			},
    			expected: []byte{
    				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    				0, 27, // Length
    				2,    // Msg Type
    				0, 0, // Withdrawn Routes Length
    				0, 4, // Total Path Attribute Length
    				64, // Attr. Flags
    				1,  // Attr. Type Code
    				1,  // Length
    				0,  // Value
    			},
    		},
    		{
    			name: "Full test",
    			msg: &BGPUpdate{
    				WithdrawnRoutes: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    					IP:     strAddr("10.0.0.0"),
    
    					Pfxlen: 8,
    					Next: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    						IP:     strAddr("192.168.0.0"),
    
    						Pfxlen: 16,
    					},
    				},
    				PathAttributes: &PathAttribute{
    					TypeCode: OriginAttr,
    					Value:    uint8(0),
    					Next: &PathAttribute{
    						TypeCode: ASPathAttr,
    
    Oliver Herms's avatar
    Oliver Herms committed
    						Value: types.ASPath{
    
    							{
    								Type: 2,
    								ASNs: []uint32{100, 155, 200},
    							},
    							{
    								Type: 1,
    								ASNs: []uint32{10, 20},
    							},
    						},
    						Next: &PathAttribute{
    							TypeCode: NextHopAttr,
    
    							Value:    bnet.IPv4FromOctets(10, 20, 30, 40),
    
    							Next: &PathAttribute{
    								TypeCode: MEDAttr,
    								Value:    uint32(100),
    								Next: &PathAttribute{
    									TypeCode: LocalPrefAttr,
    									Value:    uint32(500),
    									Next: &PathAttribute{
    										TypeCode: AtomicAggrAttr,
    										Next: &PathAttribute{
    											TypeCode: AggregatorAttr,
    											Value:    uint16(200),
    										},
    									},
    								},
    							},
    						},
    					},
    				},
    				NLRI: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    					IP:     strAddr("8.8.8.0"),
    
    					Pfxlen: 24,
    					Next: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    						IP:     strAddr("185.65.240.0"),
    
    						Pfxlen: 22,
    					},
    				},
    			},
    			expected: []byte{
    				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    
    				2, // Msg Type
    
    				// Withdraws
    				0, 5, // Withdrawn Routes Length
    				8, 10, // Withdraw 10/8
    				16, 192, 168, // Withdraw 192.168/16
    
    
    				0, 50, // Total Path Attribute Length
    
    
    				// ORIGIN
    				64, // Attr. Flags
    				1,  // Attr. Type Code
    				1,  // Length
    				0,  // Value
    				// ASPath
    				64,                     // Attr. Flags
    				2,                      // Attr. Type Code
    
    				2,                      // Path Segment Type = AS_SEQUENCE
    				3,                      // Path Segment Length
    				0, 100, 0, 155, 0, 200, // ASNs
    				1,            // Path Segment Type = AS_SET
    				2,            // Path Segment Type = AS_SET
    				0, 10, 0, 20, // ASNs
    				// Next Hop
    				64,             // Attr. Flags
    				3,              // Attr. Type Code
    				4,              // Length
    				10, 20, 30, 40, // Next Hop Address
    				// MED
    				128,          // Attr. Flags
    				4,            // Attr Type Code
    				4,            // Length
    				0, 0, 0, 100, // MED = 100
    				// LocalPref
    				64,           // Attr. Flags
    				5,            // Attr. Type Code
    				4,            // Length
    				0, 0, 1, 244, // Localpref
    				// Atomic Aggregate
    				64, // Attr. Flags
    				6,  // Attr. Type Code
    				0,  // Length
    				// Aggregator
    				192,    // Attr. Flags
    				7,      // Attr. Type Code
    				2,      // Length
    				0, 200, // Aggregator ASN = 200
    
    				// NLRI
    				24, 8, 8, 8, // 8.8.8.0/24
    				22, 185, 65, 240, // 185.65.240.0/22
    			},
    		},
    	}
    
    	for _, test := range tests {
    
    Oliver Herms's avatar
    Oliver Herms committed
    		opt := &types.Options{
    			AddPathRX: false,
    		}
    
    		res, err := test.msg.SerializeUpdate(opt)
    
    		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, res, "%s", test.name)
    	}
    }
    
    func TestSerializeAddPath(t *testing.T) {
    	tests := []struct {
    		name     string
    
    Oliver Herms's avatar
    Oliver Herms committed
    		msg      *BGPUpdate
    
    		expected []byte
    		wantFail bool
    	}{
    		{
    			name: "Withdraw only",
    
    Oliver Herms's avatar
    Oliver Herms committed
    			msg: &BGPUpdate{
    				WithdrawnRoutes: &NLRI{
    
    					PathIdentifier: 257,
    					IP:             strAddr("100.110.120.0"),
    					Pfxlen:         24,
    				},
    			},
    			expected: []byte{
    				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    				0, 31, // Length
    				2,    // Msg Type
    				0, 8, // Withdrawn Routes Length
    				0, 0, 1, 1, // Path Identifier
    				24, 100, 110, 120, // NLRI
    				0, 0, // Total Path Attribute Length
    			},
    		},
    		{
    			name: "NLRI only",
    
    Oliver Herms's avatar
    Oliver Herms committed
    			msg: &BGPUpdate{
    				NLRI: &NLRI{
    
    					PathIdentifier: 257,
    					IP:             strAddr("100.110.128.0"),
    					Pfxlen:         17,
    				},
    			},
    			expected: []byte{
    				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    				0, 31, // Length
    				2,    // Msg Type
    				0, 0, // Withdrawn Routes Length
    				0, 0, // Total Path Attribute Length
    				0, 0, 1, 1, // Path Identifier
    				17, 100, 110, 128, // NLRI
    			},
    		},
    		{
    			name: "Path Attributes only",
    
    Oliver Herms's avatar
    Oliver Herms committed
    			msg: &BGPUpdate{
    
    				PathAttributes: &PathAttribute{
    					Optional:   true,
    					Transitive: true,
    					TypeCode:   OriginAttr,
    					Value:      uint8(0), // IGP
    				},
    			},
    			expected: []byte{
    				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    				0, 27, // Length
    				2,    // Msg Type
    				0, 0, // Withdrawn Routes Length
    				0, 4, // Total Path Attribute Length
    				64, // Attr. Flags
    				1,  // Attr. Type Code
    				1,  // Length
    				0,  // Value
    			},
    		},
    		{
    			name: "Full test",
    
    Oliver Herms's avatar
    Oliver Herms committed
    			msg: &BGPUpdate{
    				WithdrawnRoutes: &NLRI{
    
    					IP:     strAddr("10.0.0.0"),
    					Pfxlen: 8,
    
    Oliver Herms's avatar
    Oliver Herms committed
    					Next: &NLRI{
    
    						IP:     strAddr("192.168.0.0"),
    						Pfxlen: 16,
    					},
    				},
    				PathAttributes: &PathAttribute{
    					TypeCode: OriginAttr,
    					Value:    uint8(0),
    					Next: &PathAttribute{
    						TypeCode: ASPathAttr,
    
    Oliver Herms's avatar
    Oliver Herms committed
    						Value: types.ASPath{
    
    							{
    								Type: 2,
    								ASNs: []uint32{100, 155, 200},
    							},
    							{
    								Type: 1,
    								ASNs: []uint32{10, 20},
    							},
    						},
    						Next: &PathAttribute{
    							TypeCode: NextHopAttr,
    
    							Value:    bnet.IPv4FromOctets(10, 20, 30, 40),
    
    							Next: &PathAttribute{
    								TypeCode: MEDAttr,
    								Value:    uint32(100),
    								Next: &PathAttribute{
    									TypeCode: LocalPrefAttr,
    									Value:    uint32(500),
    									Next: &PathAttribute{
    										TypeCode: AtomicAggrAttr,
    										Next: &PathAttribute{
    											TypeCode: AggregatorAttr,
    											Value:    uint16(200),
    										},
    									},
    								},
    							},
    						},
    					},
    				},
    
    Oliver Herms's avatar
    Oliver Herms committed
    				NLRI: &NLRI{
    
    					IP:     strAddr("8.8.8.0"),
    					Pfxlen: 24,
    
    Oliver Herms's avatar
    Oliver Herms committed
    					Next: &NLRI{
    
    						IP:     strAddr("185.65.240.0"),
    						Pfxlen: 22,
    					},
    				},
    			},
    			expected: []byte{
    				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    				0, 102, // Length
    				2, // Msg Type
    
    				// Withdraws
    				0, 13, // Withdrawn Routes Length
    				0, 0, 0, 0, // Path Identifier
    				8, 10, // Withdraw 10/8
    				0, 0, 0, 0, // Path Identifier
    				16, 192, 168, // Withdraw 192.168/16
    
    				0, 50, // Total Path Attribute Length
    
    				// ORIGIN
    				64, // Attr. Flags
    				1,  // Attr. Type Code
    				1,  // Length
    				0,  // Value
    				// ASPath
    				64,                     // Attr. Flags
    				2,                      // Attr. Type Code
    				14,                     // Attr. Length
    				2,                      // Path Segment Type = AS_SEQUENCE
    				3,                      // Path Segment Length
    				0, 100, 0, 155, 0, 200, // ASNs
    				1,            // Path Segment Type = AS_SET
    				2,            // Path Segment Type = AS_SET
    				0, 10, 0, 20, // ASNs
    				// Next Hop
    				64,             // Attr. Flags
    				3,              // Attr. Type Code
    				4,              // Length
    				10, 20, 30, 40, // Next Hop Address
    				// MED
    				128,          // Attr. Flags
    				4,            // Attr Type Code
    				4,            // Length
    				0, 0, 0, 100, // MED = 100
    				// LocalPref
    				64,           // Attr. Flags
    				5,            // Attr. Type Code
    				4,            // Length
    				0, 0, 1, 244, // Localpref
    				// Atomic Aggregate
    				64, // Attr. Flags
    				6,  // Attr. Type Code
    				0,  // Length
    				// Aggregator
    				192,    // Attr. Flags
    				7,      // Attr. Type Code
    				2,      // Length
    				0, 200, // Aggregator ASN = 200
    
    				// NLRI
    				0, 0, 0, 0, // Path Identifier
    				24, 8, 8, 8, // 8.8.8.0/24
    				0, 0, 0, 0, // Path Identifier
    				22, 185, 65, 240, // 185.65.240.0/22
    			},
    		},
    	}
    
    	for _, test := range tests {
    
    Oliver Herms's avatar
    Oliver Herms committed
    		opt := &types.Options{
    			AddPathRX: true,
    		}
    
    		res, err := test.msg.SerializeUpdate(opt)
    
    		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, res, "%s", test.name)
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    func TestFourBytesToUint32(t *testing.T) {
    	tests := []struct {
    		name     string
    		input    [4]byte
    		expected uint32
    	}{
    		{
    			name:     "Test #1",
    			input:    [4]byte{0, 0, 0, 200},
    			expected: 200,
    		},
    		{
    			name:     "Test #2",
    			input:    [4]byte{1, 0, 0, 200},
    			expected: 16777416,
    		},
    	}
    
    	for _, test := range tests {
    		res := fourBytesToUint32(test.input)
    		if res != test.expected {
    			t.Errorf("Unexpected result for test %q: Got: %d Want: %d", test.name, res, test.expected)
    		}
    	}
    }