Skip to content
Snippets Groups Projects
decoder_test.go 41.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • Oliver Herms's avatar
    Oliver Herms committed
    package packet
    
    import (
    	"bytes"
    	"fmt"
    
    Oliver Herms's avatar
    Oliver Herms committed
    	"testing"
    
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    	"github.com/bio-routing/bio-rd/net"
    
    Oliver Herms's avatar
    Oliver Herms committed
    	"github.com/stretchr/testify/assert"
    	"github.com/taktv6/tflow2/convert"
    )
    
    type test struct {
    	testNum  int
    	input    []byte
    	wantFail bool
    	expected interface{}
    }
    
    type decodeFunc func(*bytes.Buffer) (interface{}, error)
    
    func BenchmarkDecodeUpdateMsg(b *testing.B) {
    	input := []byte{0, 5, 8, 10, 16, 192, 168,
    		0, 53, // 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 Segement Length
    		59, 65, // AS15169
    		12, 248, // AS3320
    		1,      // Type = AS_SET
    		2,      // Path Segement 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, // Attribute flags
    		6, // Attribute Type code (Atomic Aggregate)
    		0, // Length
    
    		0,    // Attribute flags
    		7,    // Attribute Type code (Atomic Aggregate)
    		6,    // Length
    		1, 2, // ASN
    		10, 11, 12, 13, // Address
    
    		8, 11, // 11.0.0.0/8
    	}
    
    	for i := 0; i < b.N; i++ {
    		buf := bytes.NewBuffer(input)
    
    		_, err := decodeUpdateMsg(buf, uint16(len(input)), &Options{})
    
    Oliver Herms's avatar
    Oliver Herms committed
    		if err != nil {
    			fmt.Printf("decodeUpdateMsg failed: %v\n", err)
    		}
    		//buf.Next(1)
    	}
    }
    
    func TestDecode(t *testing.T) {
    	tests := []test{
    		{
    			// Proper packet
    			testNum: 1,
    			input: []byte{
    				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // Marker
    				0, 19, // Length
    				4, // Type = Keepalive
    
    			},
    			wantFail: false,
    			expected: &BGPMessage{
    				Header: &BGPHeader{
    					Length: 19,
    					Type:   4,
    				},
    			},
    		},
    		{
    			// Invalid marker
    			testNum: 2,
    			input: []byte{
    				1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, // Marker
    				0, 19, // Length
    				4, // Type = Keepalive
    
    			},
    			wantFail: true,
    			expected: &BGPMessage{
    				Header: &BGPHeader{
    					Length: 19,
    					Type:   4,
    				},
    			},
    		},
    		{
    			// Proper NOTIFICATION packet
    			testNum: 3,
    			input: []byte{
    				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // Marker
    				0, 21, // Length
    				3,    // Type = Notification
    				1, 1, // Message Header Error, Connection Not Synchronized.
    			},
    			wantFail: false,
    			expected: &BGPMessage{
    				Header: &BGPHeader{
    					Length: 21,
    					Type:   3,
    				},
    				Body: &BGPNotification{
    					ErrorCode:    1,
    					ErrorSubcode: 1,
    				},
    			},
    		},
    		{
    			// Proper OPEN packet
    			testNum: 4,
    			input: []byte{
    				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // Marker
    				0, 29, // Length
    				1,      // Type = Open
    				4,      // Version
    				0, 200, //ASN,
    				0, 15, // Holdtime
    				10, 20, 30, 40, // BGP Identifier
    				0, // Opt Parm Len
    			},
    			wantFail: false,
    			expected: &BGPMessage{
    				Header: &BGPHeader{
    					Length: 29,
    					Type:   1,
    				},
    				Body: &BGPOpen{
    					Version:       4,
    
    Oliver Herms's avatar
    Oliver Herms committed
    					HoldTime:      15,
    					BGPIdentifier: uint32(169090600),
    					OptParmLen:    0,
    
    Oliver Herms's avatar
    Oliver Herms committed
    				},
    			},
    		},
    		{
    			// Incomplete OPEN packet
    			testNum: 5,
    			input: []byte{
    				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // Marker
    				0, 28, // Length
    				1,      // Type = Open
    				4,      // Version
    				0, 200, //ASN,
    				0, 15, // Holdtime
    				0, 0, 0, 100, // BGP Identifier
    			},
    			wantFail: true,
    			expected: &BGPMessage{
    				Header: &BGPHeader{
    					Length: 28,
    					Type:   1,
    				},
    				Body: &BGPOpen{
    					Version:       4,
    
    Oliver Herms's avatar
    Oliver Herms committed
    					HoldTime:      15,
    					BGPIdentifier: uint32(100),
    				},
    			},
    		},
    		{
    			testNum: 6,
    			input: []byte{
    				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // Marker
    				0, 28, // Length
    				2,                               // Type = Update
    				0, 5, 8, 10, 16, 192, 168, 0, 0, // 2 withdraws
    			},
    			wantFail: false,
    			expected: &BGPMessage{
    				Header: &BGPHeader{
    					Length: 28,
    					Type:   2,
    				},
    				Body: &BGPUpdate{
    					WithdrawnRoutesLen: 5,
    					WithdrawnRoutes: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    						IP:     strAddr("10.0.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    						Pfxlen: 8,
    						Next: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    							IP:     strAddr("192.168.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    							Pfxlen: 16,
    						},
    					},
    				},
    			},
    		},
    		{
    			testNum: 7,
    			input: []byte{
    				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // Marker
    				0, 28, // Length
    				5,                               // Type = Invalid
    				0, 5, 8, 10, 16, 192, 168, 0, 0, // Some more stuff
    			},
    			wantFail: true,
    		},
    
    Oliver Herms's avatar
    Oliver Herms committed
    		{
    			testNum: 8,
    			input: []byte{
    				255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    				0, 21,
    				3,
    				6, 4,
    			},
    			wantFail: false,
    			expected: &BGPMessage{
    				Header: &BGPHeader{
    					Length: 21,
    					Type:   3,
    				},
    				Body: &BGPNotification{
    					ErrorCode:    6,
    					ErrorSubcode: 4,
    				},
    			},
    		},
    
    Oliver Herms's avatar
    Oliver Herms committed
    	}
    
    	for _, test := range tests {
    		buf := bytes.NewBuffer(test.input)
    
    		msg, err := Decode(buf, &Options{})
    
    Oliver Herms's avatar
    Oliver Herms committed
    
    		if err != nil && !test.wantFail {
    			t.Errorf("Unexpected error in test %d: %v", test.testNum, err)
    			continue
    		}
    
    		if err == nil && test.wantFail {
    			t.Errorf("Expected error did not happen in test %d", test.testNum)
    			continue
    		}
    
    		if err != nil && test.wantFail {
    			continue
    		}
    
    		if msg == nil {
    			t.Errorf("Unexpected nil result in test %d. Expected: %v", test.testNum, test.expected)
    			continue
    		}
    
    
    Oliver Herms's avatar
    Oliver Herms committed
    		assert.Equalf(t, test.expected, msg, "Test: %d", test.testNum)
    
    Oliver Herms's avatar
    Oliver Herms committed
    	}
    }
    
    func TestDecodeNotificationMsg(t *testing.T) {
    	tests := []struct {
    		name     string
    		input    []byte
    		wantFail bool
    		expected interface{}
    	}{
    		{
    			name:     "Invalid error code",
    			input:    []byte{0, 0},
    			wantFail: true,
    		},
    		{
    			name:     "Invalid error code #2",
    			input:    []byte{7, 0},
    			wantFail: true,
    		},
    		{
    			name:     "Invalid ErrSubCode (Header)",
    			input:    []byte{1, 0},
    			wantFail: true,
    		},
    		{
    			name:     "Invalid ErrSubCode (Header) #2",
    			input:    []byte{1, 4},
    			wantFail: true,
    		},
    		{
    			name:     "Invalid ErrSubCode (Open)",
    			input:    []byte{2, 0},
    			wantFail: true,
    		},
    		{
    			name:     "Invalid ErrSubCode (Open) #2",
    			input:    []byte{2, 7},
    			wantFail: true,
    		},
    		{
    			name:     "Invalid ErrSubCode (Open) #3",
    			input:    []byte{2, 5},
    			wantFail: true,
    		},
    		{
    			name:     "Invalid ErrSubCode (Update)",
    			input:    []byte{3, 0},
    			wantFail: true,
    		},
    		{
    			name:     "Invalid ErrSubCode (Update) #2",
    			input:    []byte{3, 12},
    			wantFail: true,
    		},
    		{
    			name:     "Invalid ErrSubCode (Update) #3",
    			input:    []byte{3, 7},
    			wantFail: true,
    		},
    		{
    			name:     "Valid Notification",
    			input:    []byte{2, 2},
    			wantFail: false,
    			expected: &BGPNotification{
    				ErrorCode:    2,
    				ErrorSubcode: 2,
    			},
    		},
    		{
    			name:     "Empty input",
    			input:    []byte{},
    			wantFail: true,
    		},
    		{
    			name:     "Hold Timer Expired",
    			input:    []byte{4, 0},
    			wantFail: false,
    			expected: &BGPNotification{
    				ErrorCode:    4,
    				ErrorSubcode: 0,
    			},
    		},
    		{
    			name:     "Hold Timer Expired (invalid subcode)",
    			input:    []byte{4, 1},
    			wantFail: true,
    		},
    		{
    			name:     "FSM Error",
    			input:    []byte{5, 0},
    			wantFail: false,
    			expected: &BGPNotification{
    				ErrorCode:    5,
    				ErrorSubcode: 0,
    			},
    		},
    		{
    			name:     "FSM Error (invalid subcode)",
    			input:    []byte{5, 1},
    			wantFail: true,
    		},
    		{
    			name:     "Cease",
    			input:    []byte{6, 0},
    			wantFail: false,
    			expected: &BGPNotification{
    				ErrorCode:    6,
    				ErrorSubcode: 0,
    			},
    		},
    		{
    			name:     "Cease (invalid subcode)",
    			input:    []byte{6, 1},
    			wantFail: true,
    		},
    	}
    
    	for _, test := range tests {
    		res, err := decodeNotificationMsg(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, res)
    	}
    }
    
    func TestDecodeUpdateMsg(t *testing.T) {
    	tests := []struct {
    		testNum        int
    		input          []byte
    		explicitLength uint16
    		wantFail       bool
    		expected       interface{}
    	}{
    		{
    			// 2 withdraws only, valid update
    			testNum:  1,
    			input:    []byte{0, 5, 8, 10, 16, 192, 168, 0, 0},
    			wantFail: false,
    			expected: &BGPUpdate{
    				WithdrawnRoutesLen: 5,
    				WithdrawnRoutes: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    					IP:     strAddr("10.0.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    					Pfxlen: 8,
    					Next: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    						IP:     strAddr("192.168.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    						Pfxlen: 16,
    					},
    				},
    			},
    		},
    		{
    			// 2 withdraws with one path attribute (ORIGIN), valid update
    			testNum: 2,
    			input: []byte{
    				0, 5, // Withdrawn Routes Length
    				8, 10, // 10.0.0.0/8
    				16, 192, 168, // 192.168.0.0/16
    				0, 5, // Total Path Attribute Length
    				255,  // Attribute flags
    				1,    // Attribute Type code
    				0, 1, // Length
    				2, // INCOMPLETE
    			},
    			wantFail: false,
    			expected: &BGPUpdate{
    				WithdrawnRoutesLen: 5,
    				WithdrawnRoutes: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    					IP:     strAddr("10.0.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    					Pfxlen: 8,
    					Next: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    						IP:     strAddr("192.168.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    						Pfxlen: 16,
    					},
    				},
    				TotalPathAttrLen: 5,
    				PathAttributes: &PathAttribute{
    					Optional:       true,
    					Transitive:     true,
    					Partial:        true,
    					ExtendedLength: true,
    					Length:         1,
    					TypeCode:       1,
    					Value:          uint8(2),
    				},
    			},
    		},
    		{
    			// 2 withdraws with two path attributes (ORIGIN + ASPath), valid update
    			testNum: 3,
    			input: []byte{0, 5, 8, 10, 16, 192, 168,
    				0, 14, // 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)
    				6,      // Length
    				2,      // Type = AS_SEQUENCE
    				2,      // Path Segement Length
    				59, 65, // AS15169
    				12, 248, // AS3320
    			},
    			wantFail: false,
    			expected: &BGPUpdate{
    				WithdrawnRoutesLen: 5,
    				WithdrawnRoutes: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    					IP:     strAddr("10.0.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    					Pfxlen: 8,
    					Next: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    						IP:     strAddr("192.168.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    						Pfxlen: 16,
    					},
    				},
    				TotalPathAttrLen: 14,
    				PathAttributes: &PathAttribute{
    					Optional:       true,
    					Transitive:     true,
    					Partial:        true,
    					ExtendedLength: true,
    					Length:         1,
    					TypeCode:       1,
    					Value:          uint8(2),
    					Next: &PathAttribute{
    						Optional:       false,
    						Transitive:     false,
    						Partial:        false,
    						ExtendedLength: false,
    						Length:         6,
    						TypeCode:       2,
    						Value: ASPath{
    							{
    								Type:  2,
    								Count: 2,
    								ASNs: []uint32{
    									15169,
    									3320,
    								},
    							},
    						},
    					},
    				},
    			},
    		},
    		{
    			// 2 withdraws with two path attributes (ORIGIN + ASPath), invalid AS Path segment type
    			testNum: 4,
    			input: []byte{0, 5, 8, 10, 16, 192, 168,
    				0, 13, // 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)
    				6, // Length
    				1, // Type = AS_SET
    				0, // Path Segement Length
    			},
    			wantFail: true,
    		},
    		{
    			// 2 withdraws with two path attributes (ORIGIN + ASPath), invalid AS Path segment member count
    			testNum: 5,
    			input: []byte{0, 5, 8, 10, 16, 192, 168,
    				0, 13, // 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)
    				6,      // Length
    				3,      // Type = INVALID
    				2,      // Path Segement Length
    				59, 65, // AS15169
    				12, 248, // AS3320
    			},
    			wantFail: true,
    		},
    		{
    			// 2 withdraws with two path attributes (ORIGIN + ASPath), valid update
    			testNum: 6,
    			input: []byte{0, 5, 8, 10, 16, 192, 168,
    				0, 20, // 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 Segement Length
    				59, 65, // AS15169
    				12, 248, // AS3320
    				1,      // Type = AS_SET
    				2,      // Path Segement Length
    				59, 65, // AS15169
    				12, 248, // AS3320
    			},
    			wantFail: false,
    			expected: &BGPUpdate{
    				WithdrawnRoutesLen: 5,
    				WithdrawnRoutes: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    					IP:     strAddr("10.0.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    					Pfxlen: 8,
    					Next: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    						IP:     strAddr("192.168.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    						Pfxlen: 16,
    					},
    				},
    				TotalPathAttrLen: 20,
    				PathAttributes: &PathAttribute{
    					Optional:       true,
    					Transitive:     true,
    					Partial:        true,
    					ExtendedLength: true,
    					Length:         1,
    					TypeCode:       1,
    					Value:          uint8(2),
    					Next: &PathAttribute{
    						Optional:       false,
    						Transitive:     false,
    						Partial:        false,
    						ExtendedLength: false,
    						Length:         12,
    						TypeCode:       2,
    						Value: ASPath{
    							{
    								Type:  2,
    								Count: 2,
    								ASNs: []uint32{
    									15169,
    									3320,
    								},
    							},
    							{
    								Type:  1,
    								Count: 2,
    								ASNs: []uint32{
    									15169,
    									3320,
    								},
    							},
    						},
    					},
    				},
    			},
    		},
    		{
    			// 2 withdraws with 3 path attributes (ORIGIN + ASPath, NH), valid update
    			testNum: 7,
    			input: []byte{0, 5, 8, 10, 16, 192, 168,
    				0, 27, // 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 Segement Length
    				59, 65, // AS15169
    				12, 248, // AS3320
    				1,      // Type = AS_SET
    				2,      // Path Segement Length
    				59, 65, // AS15169
    				12, 248, // AS3320
    
    				0,              // Attribute flags
    				3,              // Attribute Type code (Next Hop)
    				4,              // Length
    				10, 11, 12, 13, // Next Hop
    			},
    			wantFail: false,
    			expected: &BGPUpdate{
    				WithdrawnRoutesLen: 5,
    				WithdrawnRoutes: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    					IP:     strAddr("10.0.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    					Pfxlen: 8,
    					Next: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    						IP:     strAddr("192.168.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    						Pfxlen: 16,
    					},
    				},
    				TotalPathAttrLen: 27,
    				PathAttributes: &PathAttribute{
    
    					Optional:       true,
    					Transitive:     true,
    					Partial:        true,
    					ExtendedLength: true,
    					Length:         1,
    					TypeCode:       1,
    					Value:          uint8(2),
    					Next: &PathAttribute{
    
    						Optional:       false,
    						Transitive:     false,
    						Partial:        false,
    						ExtendedLength: false,
    						Length:         12,
    						TypeCode:       2,
    						Value: ASPath{
    							{
    								Type:  2,
    								Count: 2,
    								ASNs: []uint32{
    									15169,
    									3320,
    								},
    							},
    							{
    								Type:  1,
    								Count: 2,
    								ASNs: []uint32{
    									15169,
    									3320,
    								},
    							},
    						},
    						Next: &PathAttribute{
    							Optional:       false,
    							Transitive:     false,
    							Partial:        false,
    							ExtendedLength: false,
    							Length:         4,
    							TypeCode:       3,
    
    							Value:          strAddr("10.11.12.13"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    						},
    					},
    				},
    			},
    		},
    		{
    			// 2 withdraws with 4 path attributes (ORIGIN + ASPath, NH, MED), valid update
    			testNum: 8,
    			input: []byte{0, 5, 8, 10, 16, 192, 168,
    				0, 34, // 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 Segement Length
    				59, 65, // AS15169
    				12, 248, // AS3320
    				1,      // Type = AS_SET
    				2,      // Path Segement 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 (Next Hop)
    				4,          // Length
    				0, 0, 1, 0, // MED 256
    			},
    			wantFail: false,
    			expected: &BGPUpdate{
    				WithdrawnRoutesLen: 5,
    				WithdrawnRoutes: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    					IP:     strAddr("10.0.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    					Pfxlen: 8,
    					Next: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    						IP:     strAddr("192.168.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    						Pfxlen: 16,
    					},
    				},
    				TotalPathAttrLen: 34,
    				PathAttributes: &PathAttribute{
    
    					Optional:       true,
    					Transitive:     true,
    					Partial:        true,
    					ExtendedLength: true,
    					Length:         1,
    					TypeCode:       1,
    					Value:          uint8(2),
    					Next: &PathAttribute{
    						Optional:       false,
    						Transitive:     false,
    						Partial:        false,
    						ExtendedLength: false,
    						Length:         12,
    						TypeCode:       2,
    						Value: ASPath{
    							{
    								Type:  2,
    								Count: 2,
    								ASNs: []uint32{
    									15169,
    									3320,
    								},
    							},
    							{
    								Type:  1,
    								Count: 2,
    								ASNs: []uint32{
    									15169,
    									3320,
    								},
    							},
    						},
    						Next: &PathAttribute{
    							Optional:       false,
    							Transitive:     false,
    							Partial:        false,
    							ExtendedLength: false,
    							Length:         4,
    							TypeCode:       3,
    
    							Value:          strAddr("10.11.12.13"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    							Next: &PathAttribute{
    								Optional:       false,
    								Transitive:     false,
    								Partial:        false,
    								ExtendedLength: false,
    								Length:         4,
    								TypeCode:       4,
    								Value:          uint32(256),
    							},
    						},
    					},
    				},
    			},
    		},
    		{
    			// 2 withdraws with 4 path attributes (ORIGIN + ASPath, NH, MED, Local Pref), valid update
    			testNum: 9,
    			input: []byte{0, 5, 8, 10, 16, 192, 168,
    				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 Segement Length
    				59, 65, // AS15169
    				12, 248, // AS3320
    				1,      // Type = AS_SET
    				2,      // Path Segement 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
    			},
    			wantFail: false,
    			expected: &BGPUpdate{
    				WithdrawnRoutesLen: 5,
    				WithdrawnRoutes: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    					IP:     strAddr("10.0.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    					Pfxlen: 8,
    					Next: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    						IP:     strAddr("192.168.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    						Pfxlen: 16,
    					},
    				},
    				TotalPathAttrLen: 41,
    				PathAttributes: &PathAttribute{
    					Optional:       true,
    					Transitive:     true,
    					Partial:        true,
    					ExtendedLength: true,
    					Length:         1,
    					TypeCode:       1,
    					Value:          uint8(2),
    					Next: &PathAttribute{
    						Optional:       false,
    						Transitive:     false,
    						Partial:        false,
    						ExtendedLength: false,
    						Length:         12,
    						TypeCode:       2,
    						Value: ASPath{
    							{
    								Type:  2,
    								Count: 2,
    								ASNs: []uint32{
    									15169,
    									3320,
    								},
    							},
    							{
    								Type:  1,
    								Count: 2,
    								ASNs: []uint32{
    									15169,
    									3320,
    								},
    							},
    						},
    						Next: &PathAttribute{
    							Optional:       false,
    							Transitive:     false,
    							Partial:        false,
    							ExtendedLength: false,
    							Length:         4,
    							TypeCode:       3,
    
    							Value:          strAddr("10.11.12.13"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    							Next: &PathAttribute{
    								Optional:       false,
    								Transitive:     false,
    								Partial:        false,
    								ExtendedLength: false,
    								Length:         4,
    								TypeCode:       4,
    								Value:          uint32(256),
    								Next: &PathAttribute{
    									Optional:       false,
    									Transitive:     false,
    									Partial:        false,
    									ExtendedLength: false,
    									Length:         4,
    									TypeCode:       5,
    									Value:          uint32(256),
    								},
    							},
    						},
    					},
    				},
    			},
    		},
    		{
    			// 2 withdraws with 6 path attributes (ORIGIN, ASPath, NH, MED, Local Pref, Atomi Aggregate), valid update
    			testNum: 9,
    			input: []byte{0, 5, 8, 10, 16, 192, 168,
    				0, 44, // 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 Segement Length
    				59, 65, // AS15169
    				12, 248, // AS3320
    				1,      // Type = AS_SET
    				2,      // Path Segement 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, // Attribute flags
    				6, // Attribute Type code (Atomic Aggregate)
    				0, // Length
    			},
    			wantFail: false,
    			expected: &BGPUpdate{
    				WithdrawnRoutesLen: 5,
    				WithdrawnRoutes: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    					IP:     strAddr("10.0.0.0"),
    
    Oliver Herms's avatar
    Oliver Herms committed
    					Pfxlen: 8,
    					Next: &NLRI{
    
    Daniel Czerwonk's avatar
    Daniel Czerwonk committed
    						IP:     strAddr("192.168.0.0"),