Skip to content

Commit 34d06d9

Browse files
author
Oliver Geiselhardt-Herms
committed
ISIS: Add support for router capability TLV
1 parent f422dba commit 34d06d9

File tree

3 files changed

+212
-0
lines changed

3 files changed

+212
-0
lines changed

protocols/isis/packet/tlv.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ func readTLV(buf *bytes.Buffer) (TLV, error) {
7777
tlv, err = readISNeighborsTLV(buf, tlvType, tlvLength)
7878
case LSPEntriesTLVType:
7979
tlv, err = readLSPEntriesTLV(buf, tlvType, tlvLength)
80+
case RouterCapabilityTLVType:
81+
tlv, err = readRouterCapabilityTLV(buf, tlvType, tlvLength)
8082
default:
8183
tlv, err = readUnknownTLV(buf, tlvType, tlvLength)
8284
}
@@ -87,3 +89,12 @@ func readTLV(buf *bytes.Buffer) (TLV, error) {
8789

8890
return tlv, nil
8991
}
92+
93+
func copyTLVs(tlvs []TLV) []TLV {
94+
ret := make([]TLV, 0, len(tlvs))
95+
for _, tlv := range tlvs {
96+
ret = append(ret, tlv.Copy())
97+
}
98+
99+
return ret
100+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package packet
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
7+
"github.com/bio-routing/bio-rd/util/decode"
8+
"github.com/bio-routing/tflow2/convert"
9+
)
10+
11+
const RouterCapabilityTLVType = 242
12+
13+
type RouterCapabilityTLV struct {
14+
TLVType uint8
15+
TLVLength uint8
16+
RouterID uint32
17+
Flags uint8
18+
SubTLVs []TLV
19+
}
20+
21+
const RouterCapabilityTLVLen = 7
22+
23+
func readRouterCapabilityTLV(buf *bytes.Buffer, tlvType uint8, tlvLength uint8) (*RouterCapabilityTLV, error) {
24+
pdu := &RouterCapabilityTLV{
25+
TLVType: tlvType,
26+
TLVLength: tlvLength,
27+
}
28+
fields := []interface{}{
29+
&pdu.RouterID,
30+
&pdu.Flags,
31+
}
32+
33+
err := decode.Decode(buf, fields)
34+
if err != nil {
35+
return nil, fmt.Errorf("unable to decode fields: %v", err)
36+
}
37+
38+
toRead := tlvLength - RouterCapabilityTLVLen
39+
if toRead > 0 {
40+
tlvsBytes := make([]byte, toRead)
41+
_, err := buf.Read(tlvsBytes)
42+
if err != nil {
43+
return nil, fmt.Errorf("failed to read TLV bytes from buf: %w", err)
44+
}
45+
46+
subTLVs, err := readTLVs(bytes.NewBuffer(tlvsBytes))
47+
if err != nil {
48+
return nil, fmt.Errorf("unable to decode sub TLVs: %w", err)
49+
}
50+
51+
pdu.SubTLVs = subTLVs
52+
}
53+
54+
return pdu, nil
55+
}
56+
57+
func (r RouterCapabilityTLV) Copy() TLV {
58+
ret := r
59+
ret.SubTLVs = copyTLVs(r.SubTLVs)
60+
61+
return &ret
62+
}
63+
64+
// Type returns the type of the TLV
65+
func (r RouterCapabilityTLV) Type() uint8 {
66+
return r.TLVType
67+
}
68+
69+
// Length returns the length of the TLV
70+
func (r RouterCapabilityTLV) Length() uint8 {
71+
return r.TLVLength
72+
}
73+
74+
// Value returns the TLV itself
75+
func (r RouterCapabilityTLV) Value() interface{} {
76+
return r
77+
}
78+
79+
// Serialize serializes an WriteByte into a buffer
80+
func (r RouterCapabilityTLV) Serialize(buf *bytes.Buffer) {
81+
buf.WriteByte(r.TLVType)
82+
buf.WriteByte(r.TLVLength)
83+
buf.Write(convert.Uint32Byte(r.RouterID))
84+
buf.WriteByte(r.Flags)
85+
86+
for i := range r.SubTLVs {
87+
r.SubTLVs[i].Serialize(buf)
88+
}
89+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package packet
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestReadRouterCapabilityTLV(t *testing.T) {
11+
tests := []struct {
12+
name string
13+
tlvType uint8
14+
tlvLength uint8
15+
input []byte
16+
expectErr bool
17+
expected *RouterCapabilityTLV
18+
}{
19+
{
20+
name: "empty input",
21+
input: []byte{},
22+
expectErr: true,
23+
},
24+
{
25+
name: "valid input without sub TLVs",
26+
input: []byte{1, 2, 3, 4, 5},
27+
expectErr: false,
28+
expected: &RouterCapabilityTLV{
29+
TLVType: 242,
30+
TLVLength: 7,
31+
RouterID: 0x01020304,
32+
Flags: 5,
33+
SubTLVs: nil,
34+
},
35+
},
36+
{
37+
name: "valid input with sub TLVs",
38+
input: []byte{1, 2, 3, 4, 5, 2, 1, 3},
39+
expectErr: false,
40+
expected: &RouterCapabilityTLV{
41+
TLVType: 242,
42+
TLVLength: 10,
43+
RouterID: 0x01020304,
44+
Flags: 5,
45+
SubTLVs: []TLV{
46+
&UnknownTLV{TLVType: 2, TLVLength: 1, TLVValue: []byte{3}},
47+
},
48+
},
49+
},
50+
}
51+
52+
for _, tt := range tests {
53+
t.Run(tt.name, func(t *testing.T) {
54+
buf := bytes.NewBuffer(tt.input)
55+
result, err := readRouterCapabilityTLV(buf, 242, uint8(len(tt.input)+2))
56+
if tt.expectErr && err == nil {
57+
t.Errorf("expected error but got none for test case %s", tt.name)
58+
return
59+
}
60+
61+
if !tt.expectErr && err != nil {
62+
t.Errorf("did not expect error but got: %v for test case %s", err, tt.name)
63+
return
64+
}
65+
66+
assert.Equal(t, tt.expected, result, tt.name)
67+
})
68+
}
69+
}
70+
71+
func TestRouterCapabilityTLVSerialize(t *testing.T) {
72+
tests := []struct {
73+
name string
74+
tlv *RouterCapabilityTLV
75+
expected []byte
76+
}{
77+
{
78+
name: "serialize without sub TLVs",
79+
tlv: &RouterCapabilityTLV{
80+
TLVType: 242,
81+
TLVLength: 7,
82+
RouterID: 0x01020304,
83+
Flags: 5,
84+
SubTLVs: nil,
85+
},
86+
expected: []byte{242, 7, 1, 2, 3, 4, 5},
87+
},
88+
{
89+
name: "serialize with sub TLVs",
90+
tlv: &RouterCapabilityTLV{
91+
TLVType: 242,
92+
TLVLength: 10,
93+
RouterID: 0x01020304,
94+
Flags: 5,
95+
SubTLVs: []TLV{
96+
&UnknownTLV{TLVType: 2, TLVLength: 1, TLVValue: []byte{3}},
97+
},
98+
},
99+
expected: []byte{242, 10, 1, 2, 3, 4, 5, 2, 1, 3},
100+
},
101+
}
102+
103+
for _, tt := range tests {
104+
t.Run(tt.name, func(t *testing.T) {
105+
buf := bytes.NewBuffer(nil)
106+
tt.tlv.Serialize(buf)
107+
result := buf.Bytes()
108+
109+
assert.Equal(t, tt.expected, result, tt.name)
110+
})
111+
}
112+
}

0 commit comments

Comments
 (0)