Skip to content

Commit

Permalink
ISIS: Fix extended IP reachability TLV ser/des
Browse files Browse the repository at this point in the history
  • Loading branch information
taktv6 committed Jul 28, 2024
1 parent d55ba43 commit 4e9e8ae
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 56 deletions.
5 changes: 5 additions & 0 deletions net/ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import (
bmath "github.com/bio-routing/bio-rd/util/math"
)

const (
IPv4AddrBytes = 4
IPv6AddrBytes = 6
)

var (
v4Loopback = NewPfx(IPv4FromOctets(127, 0, 0, 0), 8).Ptr()
)
Expand Down
10 changes: 10 additions & 0 deletions net/prefix.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,13 @@ func (p *Prefix) baseAddr6() IP {

return addr
}

// BytesInAddr gets the amount of bytes needed to encode an NLRI (BGP, ISIS) of prefix length pfxlen
func BytesInAddr(pfxlen uint8) uint8 {
return uint8(math.Ceil(float64(pfxlen) / 8))
}

// BytesInPrefix gets the amount of bytes needed to encode an NLRI (BGP, ISIS)
func (p *Prefix) BytesInPrefix() uint8 {
return BytesInAddr(p.len)
}
44 changes: 44 additions & 0 deletions net/prefix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -729,3 +729,47 @@ func TestPrefixFromString(t *testing.T) {
assert.Equal(t, test.wantFail, err != nil, test.name)
}
}

func TestBytesInAddr(t *testing.T) {
tests := []struct {
name string
input uint8
expected uint8
}{
{
name: "Test #1",
input: 24,
expected: 3,
},
{
name: "Test #2",
input: 25,
expected: 4,
},
{
name: "Test #3",
input: 32,
expected: 4,
},
{
name: "Test #4",
input: 0,
expected: 0,
},
{
name: "Test #5",
input: 9,
expected: 2,
},
}

for _, test := range tests {
p := &Prefix{
len: test.input,
}
res := p.BytesInPrefix()
if res != test.expected {
t.Errorf("Unexpected result for test %q: %d", test.name, res)
}
}
}
3 changes: 2 additions & 1 deletion protocols/bgp/packet/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package packet
import (
"fmt"

"github.com/bio-routing/bio-rd/net"
bnet "github.com/bio-routing/bio-rd/net"
)

func deserializePrefix(b []byte, pfxLen uint8, afi uint16) (*bnet.Prefix, error) {
numBytes := BytesInAddr(pfxLen)
numBytes := net.BytesInAddr(pfxLen)

if numBytes != uint8(len(b)) {
return nil, fmt.Errorf("could not parse prefix of length %d. Expected %d bytes, got %d", pfxLen, numBytes, len(b))
Expand Down
11 changes: 3 additions & 8 deletions protocols/bgp/packet/nlri.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package packet
import (
"bytes"
"fmt"
"math"

"github.com/bio-routing/bio-rd/net"
bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/util/decode"
"github.com/bio-routing/tflow2/convert"
Expand Down Expand Up @@ -92,7 +92,7 @@ func decodeNLRI(buf *bytes.Buffer, afi uint16, safi uint8, addPath bool) (*NLRI,
}
}

numBytes := uint8(BytesInAddr(pfxLen))
numBytes := uint8(net.BytesInAddr(pfxLen))
bytes := make([]byte, numBytes)

r, err := buf.Read(bytes)
Expand Down Expand Up @@ -137,14 +137,9 @@ func (n *NLRI) serialize(buf *bytes.Buffer, addPath bool, safi uint8) uint8 {
}
}

pfxNumBytes := BytesInAddr(n.Prefix.Len())
pfxNumBytes := n.Prefix.BytesInPrefix()
buf.Write(n.Prefix.Addr().Bytes()[:pfxNumBytes])
numBytes += pfxNumBytes

return numBytes
}

// BytesInAddr gets the amount of bytes needed to encode an NLRI of prefix length pfxlen
func BytesInAddr(pfxlen uint8) uint8 {
return uint8(math.Ceil(float64(pfxlen) / 8))
}
41 changes: 0 additions & 41 deletions protocols/bgp/packet/nlri_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,47 +245,6 @@ func TestDecodeNLRI(t *testing.T) {
}
}

func TestBytesInAddr(t *testing.T) {
tests := []struct {
name string
input uint8
expected uint8
}{
{
name: "Test #1",
input: 24,
expected: 3,
},
{
name: "Test #2",
input: 25,
expected: 4,
},
{
name: "Test #3",
input: 32,
expected: 4,
},
{
name: "Test #4",
input: 0,
expected: 0,
},
{
name: "Test #5",
input: 9,
expected: 2,
},
}

for _, test := range tests {
res := BytesInAddr(test.input)
if res != test.expected {
t.Errorf("Unexpected result for test %q: %d", test.name, res)
}
}
}

func TestNLRISerialize(t *testing.T) {
tests := []struct {
name string
Expand Down
2 changes: 1 addition & 1 deletion protocols/bgp/server/update_sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func (u *UpdateSender) _getUpdateInformation(pathNLRIs *pathPfxs) (*packet.PathA
updatesPrefixes := make([][]*bnet.Prefix, 0, 1)
prefixes := make([]*bnet.Prefix, 0, 1)
for _, pfx := range pathNLRIs.pfxs {
budget -= int(packet.BytesInAddr(pfx.Len())) + 1
budget -= int(pfx.BytesInPrefix()) + 1

if u.options.UseAddPath {
budget -= packet.PathIdentifierLen
Expand Down
38 changes: 34 additions & 4 deletions protocols/isis/packet/tlv_extended_ip_reachability.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"

"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/util/decode"
"github.com/bio-routing/tflow2/convert"
)
Expand All @@ -14,6 +15,9 @@ const (

// ExtendedIPReachabilityLength is the length of an Extended IP Reachability excluding Sub TLVs
ExtendedIPReachabilityLength = 9

// ExtendedIPReachabilityMinLength is the minimum length of an Extended IP Reachability excluding Sub TLVs
ExtendedIPReachabilityMinLength = 5
)

// ExtendedIPReachabilityTLV is an Extended IP Reachability TLV
Expand Down Expand Up @@ -79,7 +83,7 @@ func readExtendedIPReachabilityTLV(buf *bytes.Buffer, tlvType uint8, tlvLength u
return nil, fmt.Errorf("unable to reach extended IP reachability: %w", err)
}

toRead -= ExtendedIPReachabilityLength
toRead -= ExtendedIPReachabilityLength // FIXME, this is in fact dynamic!
for i := range extIPReach.SubTLVs {
toRead -= extIPReach.SubTLVs[i].Length()
}
Expand Down Expand Up @@ -121,21 +125,29 @@ func (e *ExtendedIPReachability) Copy() *ExtendedIPReachability {
// AddExtendedIPReachability adds an extended IP reachability
func (e *ExtendedIPReachabilityTLV) AddExtendedIPReachability(eipr *ExtendedIPReachability) {
e.ExtendedIPReachabilities = append(e.ExtendedIPReachabilities, eipr)
e.TLVLength += ExtendedIPReachabilityLength
e.TLVLength += ExtendedIPReachabilityMinLength + net.BytesInAddr(eipr.pfxLen())

// TODO: Add length of sub TLVs. They will be added as soon as we support for TE
}

// Serialize serializes an ExtendedIPReachability
func (e *ExtendedIPReachability) Serialize(buf *bytes.Buffer) {
buf.Write(convert.Uint32Byte(e.Metric))
buf.WriteByte(e.UDSubBitPfxLen)
buf.Write(convert.Uint32Byte(e.Address))

n := net.BytesInAddr(e.pfxLen())
addrBytes := convert.Uint32Byte(e.Address)
buf.Write(addrBytes[:n])

for i := range e.SubTLVs {
e.SubTLVs[i].Serialize(buf)
}
}

func (e *ExtendedIPReachability) pfxLen() uint8 {
return e.UDSubBitPfxLen // FIXME!
}

func (e *ExtendedIPReachability) hasSubTLVs() bool {
return e.UDSubBitPfxLen&(uint8(1)<<6) == 64
}
Expand All @@ -151,14 +163,32 @@ func readExtendedIPReachability(buf *bytes.Buffer) (*ExtendedIPReachability, err
fields := []interface{}{
&e.Metric,
&e.UDSubBitPfxLen,
&e.Address,
}

err := decode.Decode(buf, fields)
if err != nil {
return nil, fmt.Errorf("unable to decode fields: %v", err)
}

nBytes := net.BytesInAddr(e.pfxLen())
addr := make([]byte, nBytes)
for i := 0; i < int(nBytes); i++ {
buf.Read(addr)
}

for i := len(addr); i < net.IPv4AddrBytes; i++ {
addr = append(addr, 0)
}

fields = []interface{}{
&e.Address,
}

err = decode.Decode(bytes.NewBuffer(addr), fields)
if err != nil {
return nil, fmt.Errorf("unable to decode fields: %v", err)
}

if !e.hasSubTLVs() {
return e, nil
}
Expand Down
5 changes: 4 additions & 1 deletion protocols/isis/server/lsp.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package server

import (
"fmt"

"github.com/bio-routing/bio-rd/protocols/device"
"github.com/bio-routing/bio-rd/protocols/isis/packet"
)
Expand Down Expand Up @@ -63,11 +65,12 @@ func (s *Server) extendedIPReachabilityTLV() *packet.ExtendedIPReachabilityTLV {
}

for _, addr := range ifa.ipv4Addrs() {
fmt.Printf("Adding address %s to TLV\n", addr.String())
eipr.AddExtendedIPReachability(
packet.NewExtendedIPReachability(
ifa.cfg.Level2.Metric,
addr.Len(),
addr.Addr().ToUint32()),
addr.BaseAddr().ToUint32()),
)
}
}
Expand Down

0 comments on commit 4e9e8ae

Please sign in to comment.