Skip to content
Snippets Groups Projects
Commit cff15615 authored by Oliver Herms's avatar Oliver Herms
Browse files

Cleanup

parent b1d9a59b
No related branches found
No related tags found
No related merge requests found
Showing
with 393 additions and 134 deletions
......@@ -3,31 +3,30 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"as_path.go",
"bgp.go",
"community.go",
"decoder.go",
"encoder.go",
"large_community.go",
"nlri.go",
"options.go",
"parameters.go",
"path_attribute_flags.go",
"path_attributes.go",
"update.go",
],
importpath = "github.com/bio-routing/bio-rd/protocols/bgp/packet",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/taktv6/tflow2/convert:go_default_library"],
deps = [
"//protocols/bgp/types:go_default_library",
"//route:go_default_library",
"//vendor/github.com/taktv6/tflow2/convert:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"community_test.go",
"decoder_test.go",
"encoder_test.go",
"large_community_benchmark_test.go",
"large_community_test.go",
"nlri_test.go",
"path_attributes_test.go",
],
......
......@@ -74,10 +74,6 @@ const (
EGP = 1
INCOMPLETE = 2
// ASPath Segment Types
ASSet = 1
ASSequence = 2
// NOTIFICATION Cease error SubCodes (RFC4486)
MaxPrefReached = 1
AdminShut = 2
......
......@@ -4,6 +4,8 @@ import (
"bytes"
"fmt"
"github.com/bio-routing/bio-rd/protocols/bgp/types"
"github.com/bio-routing/bio-rd/route"
"github.com/taktv6/tflow2/convert"
)
......@@ -143,27 +145,28 @@ func (pa *PathAttribute) decodeOrigin(buf *bytes.Buffer) error {
}
func (pa *PathAttribute) decodeASPath(buf *bytes.Buffer, asnLength uint8) error {
pa.Value = make(ASPath, 0)
pa.Value = make(types.ASPath, 0)
p := uint16(0)
for p < pa.Length {
segment := ASPathSegment{}
segment := types.ASPathSegment{}
count := uint8(0)
err := decode(buf, []interface{}{&segment.Type, &segment.Count})
err := decode(buf, []interface{}{&segment.Type, &count})
if err != nil {
return err
}
p += 2
if segment.Type != ASSet && segment.Type != ASSequence {
if segment.Type != types.ASSet && segment.Type != types.ASSequence {
return fmt.Errorf("Invalid AS Path segment type: %d", segment.Type)
}
if segment.Count == 0 {
return fmt.Errorf("Invalid AS Path segment length: %d", segment.Count)
if count == 0 {
return fmt.Errorf("Invalid AS Path segment length: %d", count)
}
segment.ASNs = make([]uint32, segment.Count)
for i := uint8(0); i < segment.Count; i++ {
segment.ASNs = make([]uint32, count)
for i := uint8(0); i < count; i++ {
asn, err := pa.decodeASN(buf, asnLength)
if err != nil {
return err
......@@ -173,7 +176,7 @@ func (pa *PathAttribute) decodeASPath(buf *bytes.Buffer, asnLength uint8) error
segment.ASNs[i] = asn
}
pa.Value = append(pa.Value.(ASPath), segment)
pa.Value = append(pa.Value.(types.ASPath), segment)
}
return nil
......@@ -271,10 +274,10 @@ func (pa *PathAttribute) decodeLargeCommunities(buf *bytes.Buffer) error {
}
count := pa.Length / LargeCommunityLen
coms := make([]LargeCommunity, count)
coms := make([]types.LargeCommunity, count)
for i := uint16(0); i < count; i++ {
com := LargeCommunity{}
com := types.LargeCommunity{}
v, err := read4BytesAsUint32(buf)
if err != nil {
......@@ -342,6 +345,7 @@ func (pa *PathAttribute) setLength(buf *bytes.Buffer) (int, error) {
return bytesRead, nil
}
// Copy create a copy of a path attribute
func (pa *PathAttribute) Copy() *PathAttribute {
return &PathAttribute{
ExtendedLength: pa.ExtendedLength,
......@@ -368,7 +372,8 @@ func dumpNBytes(buf *bytes.Buffer, n uint16) error {
return nil
}
func (pa *PathAttribute) serialize(buf *bytes.Buffer, opt *Options) uint8 {
// Serialize serializes a path attribute
func (pa *PathAttribute) Serialize(buf *bytes.Buffer, opt *Options) uint8 {
pathAttrLen := uint8(0)
switch pa.TypeCode {
......@@ -421,7 +426,7 @@ func (pa *PathAttribute) serializeASPath(buf *bytes.Buffer, opt *Options) uint8
length := uint8(0)
segmentsBuf := bytes.NewBuffer(nil)
for _, segment := range pa.Value.(ASPath) {
for _, segment := range pa.Value.(types.ASPath) {
segmentsBuf.WriteByte(segment.Type)
segmentsBuf.WriteByte(uint8(len(segment.ASNs)))
......@@ -523,7 +528,7 @@ func (pa *PathAttribute) serializeCommunities(buf *bytes.Buffer) uint8 {
}
func (pa *PathAttribute) serializeLargeCommunities(buf *bytes.Buffer) uint8 {
coms := pa.Value.([]LargeCommunity)
coms := pa.Value.([]types.LargeCommunity)
if len(coms) == 0 {
return 0
}
......@@ -581,3 +586,70 @@ func read4BytesAsUint32(buf *bytes.Buffer) (uint32, error) {
return fourBytesToUint32(b), nil
}
// AddOptionalPathAttributes adds optional path attributes to linked list pa
func (pa *PathAttribute) AddOptionalPathAttributes(p *route.Path) *PathAttribute {
current := pa
if len(p.BGPPath.Communities) > 0 {
communities := &PathAttribute{
TypeCode: CommunitiesAttr,
Value: p.BGPPath.Communities,
}
current.Next = communities
current = communities
}
if len(p.BGPPath.LargeCommunities) > 0 {
largeCommunities := &PathAttribute{
TypeCode: LargeCommunitiesAttr,
Value: p.BGPPath.LargeCommunities,
}
current.Next = largeCommunities
current = largeCommunities
}
return current
}
// PathAttributes converts a path object into a linked list of path attributes
func PathAttributes(p *route.Path) (*PathAttribute, error) {
asPath := &PathAttribute{
TypeCode: ASPathAttr,
Value: p.BGPPath.ASPath,
}
origin := &PathAttribute{
TypeCode: OriginAttr,
Value: p.BGPPath.Origin,
}
asPath.Next = origin
nextHop := &PathAttribute{
TypeCode: NextHopAttr,
Value: p.BGPPath.NextHop,
}
origin.Next = nextHop
localPref := &PathAttribute{
TypeCode: LocalPrefAttr,
Value: p.BGPPath.LocalPref,
}
nextHop.Next = localPref
optionals := localPref.AddOptionalPathAttributes(p)
last := optionals
for _, unknownAttr := range p.BGPPath.UnknownAttributes {
last.Next = &PathAttribute{
TypeCode: unknownAttr.TypeCode,
Optional: unknownAttr.Optional,
Transitive: unknownAttr.Transitive,
Partial: unknownAttr.Partial,
Value: unknownAttr.Value,
}
last = last.Next
}
return asPath, nil
}
......@@ -36,7 +36,7 @@ func (b *BGPUpdate) SerializeUpdate(opt *Options) ([]byte, error) {
pathAttributesBuf := bytes.NewBuffer(nil)
for pa := b.PathAttributes; pa != nil; pa = pa.Next {
paLen := int(pa.serialize(pathAttributesBuf, opt))
paLen := int(pa.Serialize(pathAttributesBuf, opt))
budget -= paLen
if budget < 0 {
return nil, fmt.Errorf("update too long")
......@@ -100,7 +100,7 @@ func (b *BGPUpdate) SerializeUpdateAddPath(opt *Options) ([]byte, error) {
pathAttributesBuf := bytes.NewBuffer(nil)
for pa := b.PathAttributes; pa != nil; pa = pa.Next {
paLen := int(pa.serialize(pathAttributesBuf, opt))
paLen := int(pa.Serialize(pathAttributesBuf, opt))
budget -= paLen
if budget < 0 {
return nil, fmt.Errorf("update too long")
......
......@@ -19,7 +19,6 @@ go_library(
"tcplistener.go",
"update_helper.go",
"update_sender.go",
"update_sender_add_path.go",
"util.go",
"withdraw.go",
],
......@@ -29,6 +28,7 @@ go_library(
"//config:go_default_library",
"//net:go_default_library",
"//protocols/bgp/packet:go_default_library",
"//protocols/bgp/types:go_default_library",
"//route:go_default_library",
"//routingtable:go_default_library",
"//routingtable/adjRIBIn:go_default_library",
......@@ -42,6 +42,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = [
"fsm_established_test.go",
"fsm_open_sent_test.go",
"fsm_test.go",
"server_test.go",
......
......@@ -7,6 +7,7 @@ import (
bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/packet"
"github.com/bio-routing/bio-rd/protocols/bgp/types"
"github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable"
"github.com/bio-routing/bio-rd/routingtable/adjRIBIn"
......@@ -230,8 +231,6 @@ func (s *establishedState) updates(u *packet.BGPUpdate) {
}
func (s *establishedState) processAttributes(attrs *packet.PathAttribute, path *route.Path) {
var currentUnknown *packet.PathAttribute
for pa := attrs; pa != nil; pa = pa.Next {
switch pa.TypeCode {
case packet.OriginAttr:
......@@ -243,33 +242,35 @@ func (s *establishedState) processAttributes(attrs *packet.PathAttribute, path *
case packet.NextHopAttr:
path.BGPPath.NextHop = pa.Value.(uint32)
case packet.ASPathAttr:
path.BGPPath.ASPath = pa.Value.(packet.ASPath)
path.BGPPath.ASPath = pa.Value.(types.ASPath)
path.BGPPath.ASPathLen = path.BGPPath.ASPath.Length()
case packet.CommunitiesAttr:
path.BGPPath.Communities = pa.Value.([]uint32)
case packet.LargeCommunitiesAttr:
path.BGPPath.LargeCommunities = pa.Value.([]packet.LargeCommunity)
path.BGPPath.LargeCommunities = pa.Value.([]types.LargeCommunity)
default:
currentUnknown = s.processUnknownAttribute(pa, currentUnknown)
if path.BGPPath.UnknownAttributes == nil {
path.BGPPath.UnknownAttributes = currentUnknown
unknownAttr := s.processUnknownAttribute(pa)
if unknownAttr != nil {
path.BGPPath.UnknownAttributes = append(path.BGPPath.UnknownAttributes)
}
}
}
}
func (s *establishedState) processUnknownAttribute(attr, current *packet.PathAttribute) *packet.PathAttribute {
func (s *establishedState) processUnknownAttribute(attr *packet.PathAttribute) *types.UnknownPathAttribute {
if !attr.Transitive {
return current
return nil
}
p := attr.Copy()
if current == nil {
return p
u := &types.UnknownPathAttribute{
Transitive: true,
Optional: attr.Optional,
Partial: attr.Partial,
TypeCode: attr.TypeCode,
Value: attr.Value.([]byte),
}
current.Next = p
return p
return u
}
func (s *establishedState) keepaliveReceived() (state, string) {
......
......@@ -5,66 +5,9 @@ import (
"io"
"github.com/bio-routing/bio-rd/protocols/bgp/packet"
"github.com/bio-routing/bio-rd/route"
log "github.com/sirupsen/logrus"
)
func pathAttribues(p *route.Path) (*packet.PathAttribute, error) {
asPath := &packet.PathAttribute{
TypeCode: packet.ASPathAttr,
Value: p.BGPPath.ASPath,
}
origin := &packet.PathAttribute{
TypeCode: packet.OriginAttr,
Value: p.BGPPath.Origin,
}
asPath.Next = origin
nextHop := &packet.PathAttribute{
TypeCode: packet.NextHopAttr,
Value: p.BGPPath.NextHop,
}
origin.Next = nextHop
localPref := &packet.PathAttribute{
TypeCode: packet.LocalPrefAttr,
Value: p.BGPPath.LocalPref,
}
nextHop.Next = localPref
if p.BGPPath != nil {
optionals := addOptionalPathAttribues(p, localPref)
optionals.Next = p.BGPPath.UnknownAttributes
}
return asPath, nil
}
func addOptionalPathAttribues(p *route.Path, parent *packet.PathAttribute) *packet.PathAttribute {
current := parent
if len(p.BGPPath.Communities) > 0 {
communities := &packet.PathAttribute{
TypeCode: packet.CommunitiesAttr,
Value: p.BGPPath.Communities,
}
current.Next = communities
current = communities
}
if len(p.BGPPath.LargeCommunities) > 0 {
largeCommunities := &packet.PathAttribute{
TypeCode: packet.LargeCommunitiesAttr,
Value: p.BGPPath.LargeCommunities,
}
current.Next = largeCommunities
current = largeCommunities
}
return current
}
func serializeAndSendUpdate(out io.Writer, update *packet.BGPUpdate, opt *packet.Options) error {
updateBytes, err := update.SerializeUpdate(opt)
if err != nil {
......
......@@ -93,7 +93,7 @@ func (u *UpdateSender) sender() {
for key, pathNLRIs := range u.toSend {
budget = packet.MaxLen - int(pathNLRIs.path.BGPPath.Length())
pathAttrs, err = pathAttribues(pathNLRIs.path)
pathAttrs, err = packet.PathAttributes(pathNLRIs.path)
if err != nil {
log.Errorf("Unable to get path attributes: %v", err)
continue
......
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"as_path.go",
"community.go",
"large_community.go",
"unknown_attribute.go",
],
importpath = "github.com/bio-routing/bio-rd/protocols/bgp/types",
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = [
"community_test.go",
"large_community_benchmark_test.go",
"large_community_test.go",
"unknown_attrinute_test.go",
],
embed = [":go_default_library"],
deps = ["//vendor/github.com/stretchr/testify/assert:go_default_library"],
)
package packet
package types
import "fmt"
// ASPath Segment Types
const (
// ASSet is the AS Path type used to indicate an AS Set (RFC4271)
ASSet = 1
// ASSequence is tha AS Path type used to indicate an AS Sequence (RFC4271)
ASSequence = 2
// MaxASNsSegment is the maximum number of ASNs in an AS segment
MaxASNsSegment = 255
)
// ASPath represents an AS Path (RFC4271)
type ASPath []ASPathSegment
// ASPathSegment represents an AS Path Segment (RFC4271)
type ASPathSegment struct {
Type uint8
Count uint8
ASNs []uint32
Type uint8
ASNs []uint32
}
// String converts an ASPath to it's human redable representation
func (pa ASPath) String() (ret string) {
for _, p := range pa {
if p.Type == ASSet {
......@@ -31,6 +45,7 @@ func (pa ASPath) String() (ret string) {
return
}
// Length returns the AS path length as used by path selection
func (pa ASPath) Length() (ret uint16) {
for _, p := range pa {
if p.Type == ASSet {
......
package packet
package types
import (
"fmt"
......@@ -7,10 +7,13 @@ import (
)
const (
WellKnownCommunityNoExport = 0xFFFFFF01
// WellKnownCommunityNoExport is the well known no export BGP community (RFC1997)
WellKnownCommunityNoExport = 0xFFFFFF01
// WellKnownCommunityNoAdvertise is the well known no advertise BGP community (RFC1997)
WellKnownCommunityNoAdvertise = 0xFFFFFF02
)
// CommunityStringForUint32 transforms a community into a human readable representation
func CommunityStringForUint32(v uint32) string {
e1 := v >> 16
e2 := v & 0x0000FFFF
......@@ -18,6 +21,7 @@ func CommunityStringForUint32(v uint32) string {
return fmt.Sprintf("(%d,%d)", e1, e2)
}
// ParseCommunityString parses human readable community representation
func ParseCommunityString(s string) (uint32, error) {
s = strings.Trim(s, "()")
t := strings.Split(s, ",")
......
package packet
package types
import (
"testing"
......
package packet
package types
import (
"fmt"
......@@ -6,16 +6,19 @@ import (
"strings"
)
// LargeCommunity represents a large community (RFC8195)
type LargeCommunity struct {
GlobalAdministrator uint32
DataPart1 uint32
DataPart2 uint32
}
// String transitions a large community to it's human readable representation
func (c *LargeCommunity) String() string {
return fmt.Sprintf("(%d,%d,%d)", c.GlobalAdministrator, c.DataPart1, c.DataPart2)
}
// ParseLargeCommunityString parses a human readable large community representation
func ParseLargeCommunityString(s string) (com LargeCommunity, err error) {
s = strings.Trim(s, "()")
t := strings.Split(s, ",")
......
package packet
package types
import (
"fmt"
......
package packet
package types
import (
"errors"
......
package types
// UnknownPathAttribute represents an unknown path attribute BIO does not support
type UnknownPathAttribute struct {
Optional bool
Transitive bool
Partial bool
TypeCode uint8
Value []byte
}
// WireLength returns the number of bytes the attribute need on the wire
func (u *UnknownPathAttribute) WireLength() uint16 {
length := uint16(len(u.Value))
if length > 255 {
length++ // Extended length
}
return length + 3
}
package types
import "testing"
func TestWireLength(t *testing.T) {
tests := []struct {
name string
pa *UnknownPathAttribute
expected uint16
}{
{
name: "Test #1",
pa: &UnknownPathAttribute{
Value: []byte{1, 2, 3},
},
expected: 6,
},
{
name: "Non extended length corner case",
pa: &UnknownPathAttribute{
Value: []byte{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255,
},
},
expected: 258,
},
{
name: "Extended length corner case",
pa: &UnknownPathAttribute{
Value: []byte{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255,
},
},
expected: 260,
},
}
for _, test := range tests {
res := test.pa.WireLength()
if res != test.expected {
t.Errorf("Unexpected result for test %q: Expected: %d Got: %d", test.name, test.expected, res)
}
}
}
......@@ -13,7 +13,7 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//net:go_default_library",
"//protocols/bgp/packet:go_default_library",
"//protocols/bgp/types:go_default_library",
"//vendor/github.com/taktv6/tflow2/convert:go_default_library",
],
)
......
......@@ -5,7 +5,7 @@ import (
"fmt"
"strings"
"github.com/bio-routing/bio-rd/protocols/bgp/packet"
"github.com/bio-routing/bio-rd/protocols/bgp/types"
"github.com/taktv6/tflow2/convert"
)
......@@ -14,7 +14,7 @@ type BGPPath struct {
PathIdentifier uint32
NextHop uint32
LocalPref uint32
ASPath packet.ASPath
ASPath types.ASPath
ASPathLen uint16
Origin uint8
MED uint32
......@@ -22,8 +22,8 @@ type BGPPath struct {
BGPIdentifier uint32
Source uint32
Communities []uint32
LargeCommunities []packet.LargeCommunity
UnknownAttributes *packet.PathAttribute
LargeCommunities []types.LargeCommunity
UnknownAttributes []types.UnknownPathAttribute
}
// Length get's the length of serialized path
......@@ -34,19 +34,12 @@ func (b *BGPPath) Length() uint16 {
asPathLen += uint16(4 * len(segment.ASNs))
}
return uint16(len(b.Communities))*7 + uint16(len(b.LargeCommunities))*15 + 4*7 + 4 + asPathLen + b.unknownAttributesLength()
}
// unknownAttributesLength calculates the length of unknown attributes
func (b *BGPPath) unknownAttributesLength() (length uint16) {
for a := b.UnknownAttributes; a != nil; a = a.Next {
length += a.Length + 3
if a.ExtendedLength {
length++
}
unknownAttributesLen := uint16(0)
for _, unknownAttr := range b.UnknownAttributes {
unknownAttributesLen += unknownAttr.WireLength()
}
return length
return uint16(len(b.Communities))*7 + uint16(len(b.LargeCommunities))*15 + 4*7 + 4 + asPathLen + unknownAttributesLen
}
// ECMP determines if routes b and c are euqal in terms of ECMP
......@@ -229,12 +222,12 @@ func (b *BGPPath) Prepend(asn uint32, times uint16) {
}
first := b.ASPath[0]
if first.Type == packet.ASSet {
if first.Type == types.ASSet {
b.insertNewASSequence()
}
for i := 0; i < int(times); i++ {
if len(b.ASPath) == packet.MaxASNsSegment {
if len(b.ASPath) == types.MaxASNsSegment {
b.insertNewASSequence()
}
......@@ -248,24 +241,34 @@ func (b *BGPPath) Prepend(asn uint32, times uint16) {
b.ASPathLen = b.ASPath.Length()
}
func (b *BGPPath) insertNewASSequence() packet.ASPath {
pa := make(packet.ASPath, len(b.ASPath)+1)
func (b *BGPPath) insertNewASSequence() types.ASPath {
pa := make(types.ASPath, len(b.ASPath)+1)
copy(pa[1:], b.ASPath)
pa[0] = packet.ASPathSegment{
ASNs: make([]uint32, 0),
Count: 0,
Type: packet.ASSequence,
pa[0] = types.ASPathSegment{
ASNs: make([]uint32, 0),
Type: types.ASSequence,
}
return pa
}
func (p *BGPPath) Copy() *BGPPath {
if p == nil {
// Copy creates a deep copy of a BGPPath
func (b *BGPPath) Copy() *BGPPath {
if b == nil {
return nil
}
cp := *p
cp := *b
cp.ASPath = make(types.ASPath, len(cp.ASPath))
copy(cp.ASPath, b.ASPath)
cp.Communities = make([]uint32, len(cp.Communities))
copy(cp.Communities, b.Communities)
cp.LargeCommunities = make([]types.LargeCommunity, len(cp.LargeCommunities))
copy(cp.LargeCommunities, b.LargeCommunities)
return &cp
}
......@@ -291,7 +294,7 @@ func (b *BGPPath) ComputeHash() string {
func (b *BGPPath) CommunitiesString() string {
str := ""
for _, com := range b.Communities {
str += packet.CommunityStringForUint32(com) + " "
str += types.CommunityStringForUint32(com) + " "
}
return strings.TrimRight(str, " ")
......
package route
import (
"bytes"
"testing"
"github.com/bio-routing/bio-rd/protocols/bgp/packet"
......@@ -64,3 +65,42 @@ func TestLargeCommunitiesString(t *testing.T) {
})
}
}
func TestLength(t *testing.T) {
tests := []struct {
name string
path *BGPPath
options packet.Options
wantFail bool
}{
{
name: "Test 1",
path: &BGPPath{},
},
}
for _, test := range tests {
calcLen := test.path.Length()
pa, err := test.path.PathAttributes()
if err != nil {
if test.wantFail {
continue
}
t.Errorf("Unexpected failure for test %q: %v", test.name, err)
continue
}
if test.wantFail {
t.Errorf("Unexpected success for test %q", test.name)
continue
}
buf := bytes.Buffer(nil)
pa.Serialize(buf, test.options)
realLen := len(buf.Bytes())
if realLen != calcLen {
t.Errorf("Unexpected result for test %q: Expected: %d Got: %d", test.name, realLen, calcLen)
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment