Skip to content

Commit bc59ab0

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

File tree

8 files changed

+789
-0
lines changed

8 files changed

+789
-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: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package packet
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
7+
"github.com/bio-routing/bio-rd/util/decode"
8+
)
9+
10+
type IPv6TERouterIDTLV struct {
11+
TLVType uint8
12+
TLVLength uint8
13+
RouterID [16]byte
14+
}
15+
16+
const IPv6TERouterIDTLVType = 12
17+
const IPv6TERouterIDTLVLength = 18
18+
19+
func readIPv6TERouterIDTLV(buf *bytes.Buffer, tlvType uint8, tlvLength uint8) (*IPv6TERouterIDTLV, error) {
20+
pdu := &IPv6TERouterIDTLV{
21+
TLVType: tlvType,
22+
TLVLength: tlvLength,
23+
}
24+
25+
fields := []any{
26+
&pdu.RouterID,
27+
}
28+
29+
err := decode.Decode(buf, fields)
30+
if err != nil {
31+
return nil, fmt.Errorf("unable to decode fields: %v", err)
32+
}
33+
34+
return pdu, nil
35+
}
36+
37+
func (i IPv6TERouterIDTLV) Copy() TLV {
38+
ret := i
39+
return &ret
40+
}
41+
42+
// Type gets the type of the TLV
43+
func (i IPv6TERouterIDTLV) Type() uint8 {
44+
return i.TLVType
45+
}
46+
47+
// Length gets the length of the TLV
48+
func (i IPv6TERouterIDTLV) Length() uint8 {
49+
return i.TLVLength
50+
}
51+
52+
// Value returns the TLV itself
53+
func (i *IPv6TERouterIDTLV) Value() any {
54+
return i
55+
}
56+
57+
func (i *IPv6TERouterIDTLV) Serialize(buf *bytes.Buffer) {
58+
buf.WriteByte(i.TLVType)
59+
buf.WriteByte(i.TLVLength)
60+
buf.Write(i.RouterID[:])
61+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package packet
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
7+
"github.com/bio-routing/bio-rd/util/decode"
8+
)
9+
10+
const NodeMaximumSIDDepthTLVType = 23
11+
const NodeMaximumSIDDepthTLVLen = 0
12+
13+
type NodeMaximumSIDDepthTLV struct {
14+
TLVType uint8
15+
TLVLength uint8
16+
MSDs []MSD
17+
}
18+
19+
type MSD struct {
20+
Type uint8
21+
Value uint8
22+
}
23+
24+
func readNodeMaximumSIDDepthTLV(buf *bytes.Buffer, tlvType uint8, tlvLength uint8) (*NodeMaximumSIDDepthTLV, error) {
25+
pdu := &NodeMaximumSIDDepthTLV{
26+
TLVType: tlvType,
27+
TLVLength: tlvLength,
28+
}
29+
30+
for i := 0; i < int(tlvLength/2); i++ {
31+
msd := MSD{}
32+
fields := []any{
33+
&msd.Type,
34+
&msd.Value,
35+
}
36+
37+
err := decode.Decode(buf, fields)
38+
if err != nil {
39+
return nil, fmt.Errorf("unable to decode fields: %v", err)
40+
}
41+
pdu.MSDs = append(pdu.MSDs, msd)
42+
}
43+
44+
return pdu, nil
45+
}
46+
47+
func (n NodeMaximumSIDDepthTLV) Copy() TLV {
48+
ret := n
49+
ret.MSDs = make([]MSD, len(n.MSDs))
50+
copy(ret.MSDs, n.MSDs)
51+
return &ret
52+
}
53+
54+
// Type gets the type of the TLV
55+
func (n NodeMaximumSIDDepthTLV) Type() uint8 {
56+
return n.TLVType
57+
}
58+
59+
// Length gets the length of the TLV
60+
func (n NodeMaximumSIDDepthTLV) Length() uint8 {
61+
return n.TLVLength
62+
}
63+
64+
// Value returns the TLV itself
65+
func (n *NodeMaximumSIDDepthTLV) Value() any {
66+
return n
67+
}
68+
69+
// Serialize serializes an NodeMaximumSIDDepthTLV
70+
func (n NodeMaximumSIDDepthTLV) Serialize(buf *bytes.Buffer) {
71+
buf.WriteByte(n.TLVType)
72+
buf.WriteByte(n.TLVLength)
73+
for _, msd := range n.MSDs {
74+
buf.WriteByte(msd.Type)
75+
buf.WriteByte(msd.Value)
76+
}
77+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
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 = 5
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+
fmt.Printf("toRead: %d\n", toRead)
40+
if toRead > 0 {
41+
tlvsBytes := make([]byte, toRead)
42+
_, err := buf.Read(tlvsBytes)
43+
if err != nil {
44+
return nil, fmt.Errorf("failed to read TLV bytes from buf: %w", err)
45+
}
46+
47+
subTLVs, err := readRouterCapSubTLVs(bytes.NewBuffer(tlvsBytes))
48+
if err != nil {
49+
return nil, fmt.Errorf("unable to decode sub TLVs: %w", err)
50+
}
51+
52+
pdu.SubTLVs = subTLVs
53+
}
54+
55+
return pdu, nil
56+
}
57+
58+
func (r RouterCapabilityTLV) Copy() TLV {
59+
ret := r
60+
ret.SubTLVs = copyTLVs(r.SubTLVs)
61+
62+
return &ret
63+
}
64+
65+
// Type returns the type of the TLV
66+
func (r RouterCapabilityTLV) Type() uint8 {
67+
return r.TLVType
68+
}
69+
70+
// Length returns the length of the TLV
71+
func (r RouterCapabilityTLV) Length() uint8 {
72+
return r.TLVLength
73+
}
74+
75+
// Value returns the TLV itself
76+
func (r RouterCapabilityTLV) Value() interface{} {
77+
return r
78+
}
79+
80+
// Serialize serializes an WriteByte into a buffer
81+
func (r RouterCapabilityTLV) Serialize(buf *bytes.Buffer) {
82+
buf.WriteByte(r.TLVType)
83+
buf.WriteByte(r.TLVLength)
84+
buf.Write(convert.Uint32Byte(r.RouterID))
85+
buf.WriteByte(r.Flags)
86+
87+
for i := range r.SubTLVs {
88+
r.SubTLVs[i].Serialize(buf)
89+
}
90+
}
91+
92+
func readRouterCapSubTLVs(buf *bytes.Buffer) ([]TLV, error) {
93+
TLVs := make([]TLV, 0)
94+
for buf.Len() > 0 {
95+
tlv, err := readRouterCapSubTLV(buf)
96+
if err != nil {
97+
return nil, fmt.Errorf("unable to read TLV: %w", err)
98+
}
99+
100+
TLVs = append(TLVs, tlv)
101+
}
102+
103+
return TLVs, nil
104+
}
105+
106+
func readRouterCapSubTLV(buf *bytes.Buffer) (TLV, error) {
107+
tlvType := uint8(0)
108+
tlvLength := uint8(0)
109+
110+
headFields := []any{
111+
&tlvType,
112+
&tlvLength,
113+
}
114+
115+
err := decode.Decode(buf, headFields)
116+
if err != nil {
117+
return nil, fmt.Errorf("unable to decode fields: %v", err)
118+
}
119+
120+
var tlv TLV
121+
switch tlvType {
122+
case SegmentRoutingCapabilityTLVType:
123+
tlv, err = readSegmentRoutingCapabilityTLV(buf, tlvType, tlvLength)
124+
case SegmentRoutingAlgorithmsTLVType:
125+
tlv, err = readSegmentRoutingAlgorithmsTLV(buf, tlvType, tlvLength)
126+
case NodeMaximumSIDDepthTLVType:
127+
tlv, err = readNodeMaximumSIDDepthTLV(buf, tlvType, tlvLength)
128+
case IPv6TERouterIDTLVType:
129+
tlv, err = readIPv6TERouterIDTLV(buf, tlvType, tlvLength)
130+
default:
131+
tlv, err = readUnknownTLV(buf, tlvType, tlvLength)
132+
}
133+
134+
if err != nil {
135+
return nil, fmt.Errorf("unable to read TLV (type %d): %v", tlvType, err)
136+
}
137+
138+
return tlv, nil
139+
}

0 commit comments

Comments
 (0)