Skip to content

Commit 7306270

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

File tree

8 files changed

+655
-0
lines changed

8 files changed

+655
-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 = 16
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 = 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 := readRouterCapSubTLVs(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+
}
90+
91+
func readRouterCapSubTLVs(buf *bytes.Buffer) ([]TLV, error) {
92+
TLVs := make([]TLV, 0)
93+
for buf.Len() > 0 {
94+
tlv, err := readRouterCapSubTLV(buf)
95+
if err != nil {
96+
return nil, fmt.Errorf("unable to read TLV: %w", err)
97+
}
98+
99+
TLVs = append(TLVs, tlv)
100+
}
101+
102+
return TLVs, nil
103+
}
104+
105+
func readRouterCapSubTLV(buf *bytes.Buffer) (TLV, error) {
106+
var err 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: %v", err)
136+
}
137+
138+
return tlv, nil
139+
}

0 commit comments

Comments
 (0)