Skip to content
Snippets Groups Projects
Unverified Commit 86f17a1f authored by takt's avatar takt Committed by GitHub
Browse files

Merge pull request #90 from bio-routing/feature/ipv6_export

Exporting IPv6 routes (including withdraws)
parents bf930b3a 2677986f
Branches
Tags
No related merge requests found
Showing
with 807 additions and 102 deletions
...@@ -45,4 +45,23 @@ func startServer(b server.BGPServer, rib *locRIB.LocRIB) { ...@@ -45,4 +45,23 @@ func startServer(b server.BGPServer, rib *locRIB.LocRIB) {
ExportFilter: filter.NewDrainFilter(), ExportFilter: filter.NewDrainFilter(),
IPv6: true, IPv6: true,
}, rib) }, rib)
b.AddPeer(config.Peer{
AdminEnabled: true,
LocalAS: 65200,
PeerAS: 65400,
PeerAddress: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0xcafe, 0, 0, 0, 5),
LocalAddress: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0xcafe),
ReconnectInterval: time.Second * 15,
HoldTime: time.Second * 90,
KeepAlive: time.Second * 30,
Passive: true,
RouterID: b.RouterID(),
AddPathSend: routingtable.ClientOptions{
BestOnly: true,
},
ImportFilter: filter.NewDrainFilter(),
ExportFilter: filter.NewAcceptAllFilter(),
IPv6: true,
}, rib)
} }
...@@ -3,7 +3,6 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") ...@@ -3,7 +3,6 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"helper.go",
"ip.go", "ip.go",
"prefix.go", "prefix.go",
], ],
...@@ -14,7 +13,6 @@ go_library( ...@@ -14,7 +13,6 @@ go_library(
go_test( go_test(
name = "go_default_test", name = "go_default_test",
srcs = [ srcs = [
"helper_test.go",
"ip_test.go", "ip_test.go",
"prefix_test.go", "prefix_test.go",
], ],
......
package net
import "net"
// IPv4ToUint32 converts an `net.IP` to an uint32 interpretation
func IPv4ToUint32(ip net.IP) uint32 {
ip = ip.To4()
return uint32(ip[3]) + uint32(ip[2])<<8 + uint32(ip[1])<<16 + uint32(ip[0])<<24
}
package net
import (
"testing"
"net"
"github.com/stretchr/testify/assert"
)
func TestIPv4ToUint32(t *testing.T) {
tests := []struct {
input []byte
expected uint32
}{
{
input: []byte{192, 168, 1, 5},
expected: 3232235781,
},
{
input: []byte{10, 0, 0, 0},
expected: 167772160,
},
{
input: []byte{172, 24, 5, 1},
expected: 2887255297,
},
{
input: net.ParseIP("172.24.5.1"),
expected: 2887255297,
},
}
for _, test := range tests {
res := IPv4ToUint32(test.input)
assert.Equal(t, test.expected, res)
}
}
...@@ -133,6 +133,20 @@ func (ip IP) bytesIPv4() []byte { ...@@ -133,6 +133,20 @@ func (ip IP) bytesIPv4() []byte {
} }
} }
// IsIPv4 returns if the `IP` is of address family IPv4
func (ip IP) IsIPv4() bool {
return ip.ipVersion == 4
}
// SizeBytes returns the number of bytes required to represent the `IP`
func (ip IP) SizeBytes() uint8 {
if ip.ipVersion == 4 {
return 4
}
return 16
}
// ToUint32 return the rightmost 32 bits of an 'IP' // ToUint32 return the rightmost 32 bits of an 'IP'
func (ip IP) ToUint32() uint32 { func (ip IP) ToUint32() uint32 {
return uint32(^uint64(0) >> 32 & ip.lower) return uint32(^uint64(0) >> 32 & ip.lower)
......
...@@ -12,8 +12,12 @@ const ( ...@@ -12,8 +12,12 @@ const (
MaxLen = 4096 MaxLen = 4096
MinUpdateLen = 4 MinUpdateLen = 4
NLRIMaxLen = 5 NLRIMaxLen = 5
AFILen = 2
SAFILen = 1
CommunityLen = 4 CommunityLen = 4
LargeCommunityLen = 12 LargeCommunityLen = 12
IPv4Len = 4
IPv6Len = 16
ClusterIDLen = 4 ClusterIDLen = 4
OpenMsg = 1 OpenMsg = 1
......
...@@ -2,7 +2,6 @@ package packet ...@@ -2,7 +2,6 @@ package packet
import ( import (
"fmt" "fmt"
"math"
bnet "github.com/bio-routing/bio-rd/net" bnet "github.com/bio-routing/bio-rd/net"
) )
...@@ -12,7 +11,7 @@ func serializePrefix(pfx bnet.Prefix) []byte { ...@@ -12,7 +11,7 @@ func serializePrefix(pfx bnet.Prefix) []byte {
return []byte{} return []byte{}
} }
numBytes := numberOfBytesForPrefixLength(pfx.Pfxlen()) numBytes := BytesInAddr(pfx.Pfxlen())
b := make([]byte, numBytes+1) b := make([]byte, numBytes+1)
b[0] = pfx.Pfxlen() b[0] = pfx.Pfxlen()
...@@ -22,7 +21,7 @@ func serializePrefix(pfx bnet.Prefix) []byte { ...@@ -22,7 +21,7 @@ func serializePrefix(pfx bnet.Prefix) []byte {
} }
func deserializePrefix(b []byte, pfxLen uint8, afi uint16) (bnet.Prefix, error) { func deserializePrefix(b []byte, pfxLen uint8, afi uint16) (bnet.Prefix, error) {
numBytes := numberOfBytesForPrefixLength(pfxLen) numBytes := BytesInAddr(pfxLen)
if numBytes != uint8(len(b)) { if numBytes != uint8(len(b)) {
return bnet.Prefix{}, fmt.Errorf("could not parse prefix of length %d. Expected %d bytes, got %d", pfxLen, numBytes, len(b)) return bnet.Prefix{}, fmt.Errorf("could not parse prefix of length %d. Expected %d bytes, got %d", pfxLen, numBytes, len(b))
...@@ -38,7 +37,3 @@ func deserializePrefix(b []byte, pfxLen uint8, afi uint16) (bnet.Prefix, error) ...@@ -38,7 +37,3 @@ func deserializePrefix(b []byte, pfxLen uint8, afi uint16) (bnet.Prefix, error)
return bnet.NewPfx(ip, pfxLen), nil return bnet.NewPfx(ip, pfxLen), nil
} }
func numberOfBytesForPrefixLength(pfxLen uint8) uint8 {
return uint8(math.Ceil(float64(pfxLen) / 8))
}
...@@ -17,7 +17,7 @@ type MultiProtocolReachNLRI struct { ...@@ -17,7 +17,7 @@ type MultiProtocolReachNLRI struct {
Prefixes []bnet.Prefix Prefixes []bnet.Prefix
} }
func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint8 { func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint16 {
nextHop := n.NextHop.Bytes() nextHop := n.NextHop.Bytes()
tempBuf := bytes.NewBuffer(nil) tempBuf := bytes.NewBuffer(nil)
...@@ -32,7 +32,7 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint8 { ...@@ -32,7 +32,7 @@ func (n *MultiProtocolReachNLRI) serialize(buf *bytes.Buffer) uint8 {
buf.Write(tempBuf.Bytes()) buf.Write(tempBuf.Bytes())
return uint8(tempBuf.Len()) return uint16(tempBuf.Len())
} }
func deserializeMultiProtocolReachNLRI(b []byte) (MultiProtocolReachNLRI, error) { func deserializeMultiProtocolReachNLRI(b []byte) (MultiProtocolReachNLRI, error) {
...@@ -67,7 +67,7 @@ func deserializeMultiProtocolReachNLRI(b []byte) (MultiProtocolReachNLRI, error) ...@@ -67,7 +67,7 @@ func deserializeMultiProtocolReachNLRI(b []byte) (MultiProtocolReachNLRI, error)
idx := uint16(0) idx := uint16(0)
for idx < uint16(len(variable)) { for idx < uint16(len(variable)) {
pfxLen := variable[idx] pfxLen := variable[idx]
numBytes := uint16(numberOfBytesForPrefixLength(pfxLen)) numBytes := uint16(BytesInAddr(pfxLen))
idx++ idx++
r := uint16(len(variable)) - idx r := uint16(len(variable)) - idx
......
...@@ -15,7 +15,7 @@ type MultiProtocolUnreachNLRI struct { ...@@ -15,7 +15,7 @@ type MultiProtocolUnreachNLRI struct {
Prefixes []bnet.Prefix Prefixes []bnet.Prefix
} }
func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint8 { func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint16 {
tempBuf := bytes.NewBuffer(nil) tempBuf := bytes.NewBuffer(nil)
tempBuf.Write(convert.Uint16Byte(n.AFI)) tempBuf.Write(convert.Uint16Byte(n.AFI))
tempBuf.WriteByte(n.SAFI) tempBuf.WriteByte(n.SAFI)
...@@ -25,7 +25,7 @@ func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint8 { ...@@ -25,7 +25,7 @@ func (n *MultiProtocolUnreachNLRI) serialize(buf *bytes.Buffer) uint8 {
buf.Write(tempBuf.Bytes()) buf.Write(tempBuf.Bytes())
return uint8(tempBuf.Len()) return uint16(tempBuf.Len())
} }
func deserializeMultiProtocolUnreachNLRI(b []byte) (MultiProtocolUnreachNLRI, error) { func deserializeMultiProtocolUnreachNLRI(b []byte) (MultiProtocolUnreachNLRI, error) {
...@@ -49,7 +49,7 @@ func deserializeMultiProtocolUnreachNLRI(b []byte) (MultiProtocolUnreachNLRI, er ...@@ -49,7 +49,7 @@ func deserializeMultiProtocolUnreachNLRI(b []byte) (MultiProtocolUnreachNLRI, er
idx := uint16(0) idx := uint16(0)
for idx < uint16(len(prefix)) { for idx < uint16(len(prefix)) {
pfxLen := prefix[idx] pfxLen := prefix[idx]
numBytes := uint16(numberOfBytesForPrefixLength(pfxLen)) numBytes := uint16(BytesInAddr(pfxLen))
idx++ idx++
r := uint16(len(prefix)) - idx r := uint16(len(prefix)) - idx
......
...@@ -3,6 +3,7 @@ package packet ...@@ -3,6 +3,7 @@ package packet
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"math"
bnet "github.com/bio-routing/bio-rd/net" bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/types" "github.com/bio-routing/bio-rd/protocols/bgp/types"
...@@ -466,6 +467,10 @@ func (pa *PathAttribute) Serialize(buf *bytes.Buffer, opt *types.Options) uint16 ...@@ -466,6 +467,10 @@ func (pa *PathAttribute) Serialize(buf *bytes.Buffer, opt *types.Options) uint16
pathAttrLen = uint16(pa.serializeCommunities(buf)) pathAttrLen = uint16(pa.serializeCommunities(buf))
case LargeCommunitiesAttr: case LargeCommunitiesAttr:
pathAttrLen = uint16(pa.serializeLargeCommunities(buf)) pathAttrLen = uint16(pa.serializeLargeCommunities(buf))
case MultiProtocolReachNLRICode:
pathAttrLen = pa.serializeMultiProtocolReachNLRI(buf)
case MultiProtocolUnreachNLRICode:
pathAttrLen = pa.serializeMultiProtocolUnreachNLRI(buf)
case OriginatorIDAttr: case OriginatorIDAttr:
pathAttrLen = uint16(pa.serializeOriginatorID(buf)) pathAttrLen = uint16(pa.serializeOriginatorID(buf))
case ClusterListAttr: case ClusterListAttr:
...@@ -690,6 +695,62 @@ func (pa *PathAttribute) serializeUnknownAttribute(buf *bytes.Buffer) uint16 { ...@@ -690,6 +695,62 @@ func (pa *PathAttribute) serializeUnknownAttribute(buf *bytes.Buffer) uint16 {
return uint16(len(b) + 2) return uint16(len(b) + 2)
} }
func (pa *PathAttribute) serializeMultiProtocolReachNLRI(buf *bytes.Buffer) uint16 {
v := pa.Value.(MultiProtocolReachNLRI)
pa.Optional = true
tempBuf := bytes.NewBuffer(nil)
v.serialize(tempBuf)
return pa.serializeGeneric(tempBuf.Bytes(), buf)
}
func (pa *PathAttribute) serializeMultiProtocolUnreachNLRI(buf *bytes.Buffer) uint16 {
v := pa.Value.(MultiProtocolUnreachNLRI)
pa.Optional = true
tempBuf := bytes.NewBuffer(nil)
v.serialize(tempBuf)
return pa.serializeGeneric(tempBuf.Bytes(), buf)
}
func (pa *PathAttribute) serializeGeneric(b []byte, buf *bytes.Buffer) uint16 {
attrFlags := uint8(0)
if pa.Optional {
attrFlags = setOptional(attrFlags)
}
if pa.Transitive {
attrFlags = setTransitive(attrFlags)
}
if len(b) > math.MaxUint8 {
pa.ExtendedLength = true
}
if pa.ExtendedLength {
attrFlags = setExtendedLength(attrFlags)
}
if pa.Transitive {
attrFlags = setTransitive(attrFlags)
}
buf.WriteByte(attrFlags)
buf.WriteByte(pa.TypeCode)
if pa.ExtendedLength {
l := len(b)
buf.WriteByte(uint8(l >> 8))
buf.WriteByte(uint8(l & 0x0000FFFF))
} else {
buf.WriteByte(uint8(len(b)))
}
buf.Write(b)
return uint16(len(b) + 2)
}
func fourBytesToUint32(address [4]byte) uint32 { func fourBytesToUint32(address [4]byte) uint32 {
return uint32(address[0])<<24 + uint32(address[1])<<16 + uint32(address[2])<<8 + uint32(address[3]) return uint32(address[0])<<24 + uint32(address[1])<<16 + uint32(address[2])<<8 + uint32(address[3])
} }
...@@ -765,7 +826,7 @@ func PathAttributes(p *route.Path, iBGP bool, rrClient bool) (*PathAttribute, er ...@@ -765,7 +826,7 @@ func PathAttributes(p *route.Path, iBGP bool, rrClient bool) (*PathAttribute, er
if p.BGPPath.Aggregator != nil { if p.BGPPath.Aggregator != nil {
aggregator := &PathAttribute{ aggregator := &PathAttribute{
TypeCode: AggregatorAttr, TypeCode: AggregatorAttr,
Value: p.BGPPath.Aggregator, Value: *p.BGPPath.Aggregator,
} }
last.Next = aggregator last.Next = aggregator
last = aggregator last = aggregator
......
...@@ -259,6 +259,8 @@ func (s *establishedState) newRoutePath() *route.Path { ...@@ -259,6 +259,8 @@ func (s *establishedState) newRoutePath() *route.Path {
} }
func (s *establishedState) multiProtocolUpdate(path *route.Path, nlri packet.MultiProtocolReachNLRI) { func (s *establishedState) multiProtocolUpdate(path *route.Path, nlri packet.MultiProtocolReachNLRI) {
path.BGPPath.NextHop = nlri.NextHop
for _, pfx := range nlri.Prefixes { for _, pfx := range nlri.Prefixes {
s.fsm.adjRIBIn.AddPath(pfx, path) s.fsm.adjRIBIn.AddPath(pfx, path)
} }
......
...@@ -86,8 +86,11 @@ func (u *UpdateSender) sender(aggrTime time.Duration) { ...@@ -86,8 +86,11 @@ func (u *UpdateSender) sender(aggrTime time.Duration) {
u.toSendMu.Lock() u.toSendMu.Lock()
overhead := u.updateOverhead()
for key, pathNLRIs := range u.toSend { for key, pathNLRIs := range u.toSend {
budget = packet.MaxLen - packet.HeaderLen - packet.MinUpdateLen - int(pathNLRIs.path.BGPPath.Length()) budget = packet.MaxLen - packet.HeaderLen - packet.MinUpdateLen - int(pathNLRIs.path.BGPPath.Length()) - overhead
pathAttrs, err = packet.PathAttributes(pathNLRIs.path, u.iBGP, u.rrClient) pathAttrs, err = packet.PathAttributes(pathNLRIs.path, u.iBGP, u.rrClient)
if err != nil { if err != nil {
log.Errorf("Unable to get path attributes: %v", err) log.Errorf("Unable to get path attributes: %v", err)
...@@ -98,10 +101,11 @@ func (u *UpdateSender) sender(aggrTime time.Duration) { ...@@ -98,10 +101,11 @@ func (u *UpdateSender) sender(aggrTime time.Duration) {
prefixes := make([]bnet.Prefix, 0, 1) prefixes := make([]bnet.Prefix, 0, 1)
for _, pfx := range pathNLRIs.pfxs { for _, pfx := range pathNLRIs.pfxs {
budget -= int(packet.BytesInAddr(pfx.Pfxlen())) + 1 budget -= int(packet.BytesInAddr(pfx.Pfxlen())) + 1
if budget < 0 { if budget < 0 {
updatesPrefixes = append(updatesPrefixes, prefixes) updatesPrefixes = append(updatesPrefixes, prefixes)
prefixes = make([]bnet.Prefix, 0, 1) prefixes = make([]bnet.Prefix, 0, 1)
budget = packet.MaxLen - int(pathNLRIs.path.BGPPath.Length()) budget = packet.MaxLen - int(pathNLRIs.path.BGPPath.Length()) - overhead
} }
prefixes = append(prefixes, pfx) prefixes = append(prefixes, pfx)
...@@ -120,35 +124,97 @@ func (u *UpdateSender) sender(aggrTime time.Duration) { ...@@ -120,35 +124,97 @@ func (u *UpdateSender) sender(aggrTime time.Duration) {
} }
} }
func (u *UpdateSender) updateOverhead() int {
// TODO: for multi RIB support we need the AFI/SAFI combination to determine overhead. For now: MultiProtocol = IPv6
if u.fsm.options.SupportsMultiProtocol {
// since we are replacing the next hop attribute IPv4Len has to be subtracted, we also add another byte for extended length
return packet.AFILen + packet.SAFILen + 1 + packet.IPv6Len - packet.IPv4Len + 1
}
return 0
}
func (u *UpdateSender) sendUpdates(pathAttrs *packet.PathAttribute, updatePrefixes [][]bnet.Prefix, pathID uint32) { func (u *UpdateSender) sendUpdates(pathAttrs *packet.PathAttribute, updatePrefixes [][]bnet.Prefix, pathID uint32) {
var nlri *packet.NLRI
var err error var err error
for _, prefixes := range updatePrefixes {
update := u.updateMessageForPrefixes(prefixes, pathAttrs, pathID)
for _, updatePrefix := range updatePrefixes { err = serializeAndSendUpdate(u.fsm.con, update, u.fsm.options)
update := &packet.BGPUpdate{ if err != nil {
PathAttributes: pathAttrs, log.Errorf("Failed to serialize and send: %v", err)
} }
}
}
for _, pfx := range updatePrefix { func (u *UpdateSender) updateMessageForPrefixes(pfxs []bnet.Prefix, pa *packet.PathAttribute, pathID uint32) *packet.BGPUpdate {
nlri = &packet.NLRI{ if u.fsm.options.SupportsMultiProtocol {
PathIdentifier: pathID, return u.bgpUpdateMultiProtocol(pfxs, pa, pathID)
IP: pfx.Addr().ToUint32(), }
Pfxlen: pfx.Pfxlen(),
Next: update.NLRI, return u.bgpUpdate(pfxs, pa, pathID)
} }
update.NLRI = nlri
func (u *UpdateSender) bgpUpdate(pfxs []bnet.Prefix, pa *packet.PathAttribute, pathID uint32) *packet.BGPUpdate {
update := &packet.BGPUpdate{
PathAttributes: pa,
}
var nlri *packet.NLRI
for _, pfx := range pfxs {
nlri = &packet.NLRI{
PathIdentifier: pathID,
IP: pfx.Addr().ToUint32(),
Pfxlen: pfx.Pfxlen(),
Next: update.NLRI,
} }
update.NLRI = nlri
}
err = serializeAndSendUpdate(u.fsm.con, update, u.fsm.options) return update
if err != nil { }
log.Errorf("Failed to serialize and send: %v", err)
func (u *UpdateSender) bgpUpdateMultiProtocol(pfxs []bnet.Prefix, pa *packet.PathAttribute, pathID uint32) *packet.BGPUpdate {
pa, nextHop := u.copyAttributesWithoutNextHop(pa)
attrs := &packet.PathAttribute{
TypeCode: packet.MultiProtocolReachNLRICode,
Value: packet.MultiProtocolReachNLRI{
AFI: packet.IPv6AFI,
SAFI: packet.UnicastSAFI,
NextHop: nextHop,
Prefixes: pfxs,
},
}
attrs.Next = pa
return &packet.BGPUpdate{
PathAttributes: attrs,
}
}
func (u *UpdateSender) copyAttributesWithoutNextHop(pa *packet.PathAttribute) (attrs *packet.PathAttribute, nextHop bnet.IP) {
var curCopy, lastCopy *packet.PathAttribute
for cur := pa; cur != nil; cur = cur.Next {
if cur.TypeCode == packet.NextHopAttr {
nextHop = cur.Value.(bnet.IP)
} else {
curCopy = cur.Copy()
if lastCopy == nil {
attrs = curCopy
} else {
lastCopy.Next = curCopy
}
lastCopy = curCopy
} }
} }
return attrs, nextHop
} }
// RemovePath withdraws prefix `pfx` from a peer // RemovePath withdraws prefix `pfx` from a peer
func (u *UpdateSender) RemovePath(pfx bnet.Prefix, p *route.Path) bool { func (u *UpdateSender) RemovePath(pfx bnet.Prefix, p *route.Path) bool {
err := withDrawPrefixesAddPath(u.fsm.con, u.fsm.options, pfx, p) err := u.withdrawPrefix(pfx, p)
if err != nil { if err != nil {
log.Errorf("Unable to withdraw prefix: %v", err) log.Errorf("Unable to withdraw prefix: %v", err)
return false return false
...@@ -156,6 +222,14 @@ func (u *UpdateSender) RemovePath(pfx bnet.Prefix, p *route.Path) bool { ...@@ -156,6 +222,14 @@ func (u *UpdateSender) RemovePath(pfx bnet.Prefix, p *route.Path) bool {
return true return true
} }
func (u *UpdateSender) withdrawPrefix(pfx bnet.Prefix, p *route.Path) error {
if u.fsm.options.SupportsMultiProtocol {
return withDrawPrefixesMultiProtocol(u.fsm.con, u.fsm.options, pfx)
}
return withDrawPrefixesAddPath(u.fsm.con, u.fsm.options, pfx, p)
}
// UpdateNewClient does nothing // UpdateNewClient does nothing
func (u *UpdateSender) UpdateNewClient(client routingtable.RouteTableClient) error { func (u *UpdateSender) UpdateNewClient(client routingtable.RouteTableClient) error {
log.Warningf("BGP Update Sender: UpdateNewClient not implemented") log.Warningf("BGP Update Sender: UpdateNewClient not implemented")
......
This diff is collapsed.
...@@ -58,3 +58,17 @@ func withDrawPrefixesAddPath(out io.Writer, opt *types.Options, pfx net.Prefix, ...@@ -58,3 +58,17 @@ func withDrawPrefixesAddPath(out io.Writer, opt *types.Options, pfx net.Prefix,
} }
return serializeAndSendUpdate(out, update, opt) return serializeAndSendUpdate(out, update, opt)
} }
func withDrawPrefixesMultiProtocol(out io.Writer, opt *types.Options, pfx net.Prefix) error {
update := &packet.BGPUpdate{
PathAttributes: &packet.PathAttribute{
TypeCode: packet.MultiProtocolUnreachNLRICode,
Value: packet.MultiProtocolUnreachNLRI{
AFI: packet.IPv6AFI,
SAFI: packet.UnicastSAFI,
Prefixes: []net.Prefix{pfx},
},
},
}
return serializeAndSendUpdate(out, update, opt)
}
...@@ -61,6 +61,46 @@ func TestWithDrawPrefixes(t *testing.T) { ...@@ -61,6 +61,46 @@ func TestWithDrawPrefixes(t *testing.T) {
} }
} }
func TestWithDrawPrefixesMultiProtocol(t *testing.T) {
tests := []struct {
Name string
Prefix net.Prefix
Expected []byte
}{
{
Name: "IPv6 MP_UNREACH_NLRI",
Prefix: net.NewPfx(net.IPv6FromBlocks(0x2804, 0x148c, 0, 0, 0, 0, 0, 0), 32),
Expected: []byte{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // BGP Marker
0x00, 0x22, // BGP Message Length
0x02, // BGP Message Type == Update
0x00, 0x00, // WithDraw Octet length
0x00, 0x0b, // Length
0x80, // Flags
0x0f, // Attribute Code
0x08, // Attribute length
0x00, 0x02, // AFI
0x01, // SAFI
0x20, 0x28, 0x04, 0x14, 0x8c, // Prefix
},
},
}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
opt := &types.Options{
AddPathRX: false,
}
err := withDrawPrefixesMultiProtocol(buf, opt, test.Prefix)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
assert.Equal(t, test.Expected, buf.Bytes())
})
}
}
func TestWithDrawPrefixesAddPath(t *testing.T) { func TestWithDrawPrefixesAddPath(t *testing.T) {
testcases := []struct { testcases := []struct {
Name string Name string
......
...@@ -5,9 +5,10 @@ import ( ...@@ -5,9 +5,10 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/taktv6/tflow2/convert"
bnet "github.com/bio-routing/bio-rd/net" bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/types" "github.com/bio-routing/bio-rd/protocols/bgp/types"
"github.com/taktv6/tflow2/convert"
) )
// BGPPath represents a set of BGP path attributes // BGPPath represents a set of BGP path attributes
...@@ -253,7 +254,7 @@ func (b *BGPPath) Print() string { ...@@ -253,7 +254,7 @@ func (b *BGPPath) Print() string {
ret += fmt.Sprintf("\t\tLargeCommunities: %v\n", b.LargeCommunities) ret += fmt.Sprintf("\t\tLargeCommunities: %v\n", b.LargeCommunities)
if b.OriginatorID != 0 { if b.OriginatorID != 0 {
oid := uint32To4Byte(b.OriginatorID) oid := convert.Uint32Byte(b.OriginatorID)
ret += fmt.Sprintf("\t\tOriginatorID: %d.%d.%d.%d\n", oid[0], oid[1], oid[2], oid[3]) ret += fmt.Sprintf("\t\tOriginatorID: %d.%d.%d.%d\n", oid[0], oid[1], oid[2], oid[3])
} }
if b.ClusterList != nil { if b.ClusterList != nil {
...@@ -331,7 +332,7 @@ func (b *BGPPath) Copy() *BGPPath { ...@@ -331,7 +332,7 @@ func (b *BGPPath) Copy() *BGPPath {
// ComputeHash computes an hash over all attributes of the path // ComputeHash computes an hash over all attributes of the path
func (b *BGPPath) ComputeHash() string { func (b *BGPPath) ComputeHash() string {
s := fmt.Sprintf("%s\t%d\t%v\t%d\t%d\t%v\t%d\t%s\t%v\t%v\t%d", s := fmt.Sprintf("%s\t%d\t%v\t%d\t%d\t%v\t%d\t%s\t%v\t%v\t%d\t%d\t%v",
b.NextHop, b.NextHop,
b.LocalPref, b.LocalPref,
b.ASPath, b.ASPath,
...@@ -341,10 +342,10 @@ func (b *BGPPath) ComputeHash() string { ...@@ -341,10 +342,10 @@ func (b *BGPPath) ComputeHash() string {
b.BGPIdentifier, b.BGPIdentifier,
b.Source, b.Source,
b.Communities, b.Communities,
b.OriginatorID,
b.ClusterList,
b.LargeCommunities, b.LargeCommunities,
b.PathIdentifier) b.PathIdentifier,
b.OriginatorID,
b.ClusterList)
return fmt.Sprintf("%x", sha256.Sum256([]byte(s))) return fmt.Sprintf("%x", sha256.Sum256([]byte(s)))
} }
...@@ -363,7 +364,7 @@ func (b *BGPPath) CommunitiesString() string { ...@@ -363,7 +364,7 @@ func (b *BGPPath) CommunitiesString() string {
func (b *BGPPath) ClusterListString() string { func (b *BGPPath) ClusterListString() string {
str := "" str := ""
for _, cid := range b.ClusterList { for _, cid := range b.ClusterList {
octes := uint32To4Byte(cid) octes := convert.Uint32Byte(cid)
str += fmt.Sprintf("%d.%d.%d.%d ", octes[0], octes[1], octes[2], octes[3]) str += fmt.Sprintf("%d.%d.%d.%d ", octes[0], octes[1], octes[2], octes[3])
} }
...@@ -379,14 +380,3 @@ func (b *BGPPath) LargeCommunitiesString() string { ...@@ -379,14 +380,3 @@ func (b *BGPPath) LargeCommunitiesString() string {
return strings.TrimRight(str, " ") return strings.TrimRight(str, " ")
} }
func uint32To4Byte(addr uint32) [4]byte {
slice := convert.Uint32Byte(addr)
ret := [4]byte{
slice[0],
slice[1],
slice[2],
slice[3],
}
return ret
}
...@@ -36,9 +36,9 @@ func TestComputeHash(t *testing.T) { ...@@ -36,9 +36,9 @@ func TestComputeHash(t *testing.T) {
Source: bnet.IPv4(4), Source: bnet.IPv4(4),
} }
assert.Equal(t, "1058916ff3e6a51c7d8a47945d13fc3fcd8ee578a6d376505f46d58979b30fae", p.ComputeHash()) assert.Equal(t, "5907ed8960ccc14eed8f1a34a8eb3e6c82a8dd947d6cbf67eb58ca292f4588d5", p.ComputeHash())
p.LocalPref = 150 p.LocalPref = 150
assert.NotEqual(t, "1058916ff3e6a51c7d8a47945d13fc3fcd8ee578a6d376505f46d58979b30fae", p.ComputeHash()) assert.NotEqual(t, "5907ed8960ccc14eed8f1a34a8eb3e6c82a8dd947d6cbf67eb58ca292f4588d5", p.ComputeHash())
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment