Skip to content
Snippets Groups Projects
Unverified Commit 0b46519c authored by Daniel Czerwonk's avatar Daniel Czerwonk Committed by GitHub
Browse files

Merge branch 'master' into fix/pathmgr

parents 2a631828 cfcf9c8c
Branches
Tags
No related merge requests found
Showing
with 330 additions and 135 deletions
......@@ -22,8 +22,8 @@ script:
- mkdir -p $HOME/gopath/src/github.com/bio-routing/
- ln -s $TRAVIS_BUILD_DIR $HOME/gopath/src/github.com/bio-routing/bio-rd || true
- cp .bazelrc.travis .bazelrc
- bazel build //vendor/github.com/mattn/goveralls
- bazel test //...
- bazel coverage //...
- bazel-bin/vendor/github.com/mattn/goveralls/linux_amd64_stripped/goveralls -coverprofile=$(find bazel-testlogs/ -name coverage.dat | paste -sd "," -)
- bazel build //vendor/github.com/q3k/goveralls
- bazel-bin/vendor/github.com/q3k/goveralls/linux_amd64_stripped/goveralls -coverprofile=$(find bazel-testlogs/ -iname coverage.dat -or -iname baseline_coverage.dat | paste -sd ',') -merge=false
......@@ -46,7 +46,7 @@
"gps/internal/pb",
"gps/paths",
"gps/pkgtree",
"internal/fs"
"internal/fs",
]
revision = "37d9ea0ac16f0e0a05afc3b60e1ac8c364b6c329"
version = "v0.4.1"
......@@ -63,12 +63,6 @@
revision = "8b28145dffc87104e66d074f62ea8080edfad7c8"
version = "v0.3.0"
[[projects]]
name = "github.com/mattn/goveralls"
packages = ["."]
revision = "b71a1e4855f87991aff01c2c833a75a07059c61c"
version = "v0.0.2"
[[projects]]
branch = "master"
name = "github.com/nightlyone/lockfile"
......@@ -93,6 +87,12 @@
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
name = "github.com/q3k/goveralls"
packages = ["."]
revision = "789b29cb81d4de953738cec0fbaefa8af2ff4ea2"
version = "v0.1.0"
[[projects]]
branch = "master"
name = "github.com/sdboyer/constext"
......@@ -140,7 +140,7 @@
name = "golang.org/x/sys"
packages = [
"unix",
"windows"
"windows",
]
revision = "bb9c189858d91f42db229b04d45a4c3d23a7662a"
......@@ -153,6 +153,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "54ddfce69bb4724edb07fa628b5a6ae7a4fb1af7ba00b2a64fe043d967d2fdff"
inputs-digest = "8d26786e7bd681598d376675bc030c802da70ac1e285fe39220d11970e1036c4"
solver-name = "gps-cdcl"
solver-version = 1
......@@ -19,7 +19,7 @@
# name = "github.com/x/y"
# version = "2.4.0"
required = ["github.com/golang/dep", "github.com/mattn/goveralls", "github.com/go-yaml/yaml"]
required = ["github.com/golang/dep", "github.com/q3k/goveralls", "github.com/go-yaml/yaml"]
[prune]
go-tests = true
......
......@@ -40,7 +40,7 @@ Update vendor/dependencies
After updating Gopkg.toml, run
bazel build //vendor/github.com/golang/dep/cmd/dep
bazel-bin/vendor/github.com/golang/dep/cmd/dep/linux_amd64_stripped/dep
bazel-bin/vendor/github.com/golang/dep/cmd/dep/linux_amd64_stripped/dep use
# hack: dep of dep gives us these, and it breaks gazelle
rm -rf vendor/github.com/golang/dep/cmd/dep/testdata
rm -rf vendor/github.com/golang/dep/internal/fs/testdata/symlinks/dir-symlink
......@@ -40,9 +40,9 @@ func main() {
b.AddPeer(config.Peer{
AdminEnabled: true,
LocalAS: 6695,
LocalAS: 65200,
PeerAS: 65300,
PeerAddress: net.IP([]byte{169, 254, 200, 1}),
PeerAddress: net.IP([]byte{172, 17, 0, 3}),
LocalAddress: net.IP([]byte{169, 254, 200, 0}),
ReconnectInterval: time.Second * 15,
HoldTime: time.Second * 90,
......@@ -59,9 +59,9 @@ func main() {
b.AddPeer(config.Peer{
AdminEnabled: true,
LocalAS: 6695,
LocalAS: 65200,
PeerAS: 65100,
PeerAddress: net.IP([]byte{169, 254, 100, 0}),
PeerAddress: net.IP([]byte{172, 17, 0, 2}),
LocalAddress: net.IP([]byte{169, 254, 100, 1}),
ReconnectInterval: time.Second * 15,
HoldTime: time.Second * 90,
......@@ -79,7 +79,7 @@ func main() {
go func() {
for {
fmt.Print(rib.Print())
fmt.Printf("LocRIB count: %d\n", rib.Count())
time.Sleep(time.Second * 10)
}
}()
......
......@@ -9,6 +9,7 @@ go_library(
"encoder.go",
"large_community.go",
"nlri.go",
"options.go",
"parameters.go",
"path_attribute_flags.go",
"path_attributes.go",
......
......@@ -92,9 +92,11 @@ const (
UnicastSAFI = 1
CapabilitiesParamType = 2
AddPathCapabilityCode = 69
ASN4CapabilityCode = 65
AddPathReceive = 1
AddPathSend = 2
AddPathSendReceive = 3
ASTransASN = 23456
)
type BGPError struct {
......@@ -119,7 +121,7 @@ type BGPHeader struct {
type BGPOpen struct {
Version uint8
AS uint16
ASN uint16
HoldTime uint16
BGPIdentifier uint32
OptParmLen uint8
......
......@@ -10,13 +10,13 @@ import (
)
// Decode decodes a BGP message
func Decode(buf *bytes.Buffer) (*BGPMessage, error) {
func Decode(buf *bytes.Buffer, opt *Options) (*BGPMessage, error) {
hdr, err := decodeHeader(buf)
if err != nil {
return nil, fmt.Errorf("Failed to decode header: %v", err)
}
body, err := decodeMsgBody(buf, hdr.Type, hdr.Length-MinLen)
body, err := decodeMsgBody(buf, hdr.Type, hdr.Length-MinLen, opt)
if err != nil {
return nil, fmt.Errorf("Failed to decode message: %v", err)
}
......@@ -27,12 +27,12 @@ func Decode(buf *bytes.Buffer) (*BGPMessage, error) {
}, nil
}
func decodeMsgBody(buf *bytes.Buffer, msgType uint8, l uint16) (interface{}, error) {
func decodeMsgBody(buf *bytes.Buffer, msgType uint8, l uint16, opt *Options) (interface{}, error) {
switch msgType {
case OpenMsg:
return decodeOpenMsg(buf)
case UpdateMsg:
return decodeUpdateMsg(buf, l)
return decodeUpdateMsg(buf, l, opt)
case KeepaliveMsg:
return nil, nil // Nothing to decode in Keepalive message
case NotificationMsg:
......@@ -41,7 +41,7 @@ func decodeMsgBody(buf *bytes.Buffer, msgType uint8, l uint16) (interface{}, err
return nil, fmt.Errorf("Unknown message type: %d", msgType)
}
func decodeUpdateMsg(buf *bytes.Buffer, l uint16) (*BGPUpdate, error) {
func decodeUpdateMsg(buf *bytes.Buffer, l uint16, opt *Options) (*BGPUpdate, error) {
msg := &BGPUpdate{}
err := decode(buf, []interface{}{&msg.WithdrawnRoutesLen})
......@@ -59,7 +59,7 @@ func decodeUpdateMsg(buf *bytes.Buffer, l uint16) (*BGPUpdate, error) {
return msg, err
}
msg.PathAttributes, err = decodePathAttrs(buf, msg.TotalPathAttrLen)
msg.PathAttributes, err = decodePathAttrs(buf, msg.TotalPathAttrLen, opt)
if err != nil {
return msg, err
}
......@@ -141,7 +141,7 @@ func _decodeOpenMsg(buf *bytes.Buffer) (interface{}, error) {
fields := []interface{}{
&msg.Version,
&msg.AS,
&msg.ASN,
&msg.HoldTime,
&msg.BGPIdentifier,
&msg.OptParmLen,
......@@ -238,6 +238,12 @@ func decodeCapability(buf *bytes.Buffer) (Capability, error) {
return cap, fmt.Errorf("Unable to decode add path capability")
}
cap.Value = addPathCap
case ASN4CapabilityCode:
asn4Cap, err := decodeASN4Capability(buf)
if err != nil {
return cap, fmt.Errorf("Unable to decode 4 octet ASN capability")
}
cap.Value = asn4Cap
default:
for i := uint8(0); i < cap.Length; i++ {
_, err := buf.ReadByte()
......@@ -266,6 +272,20 @@ func decodeAddPathCapability(buf *bytes.Buffer) (AddPathCapability, error) {
return addPathCap, nil
}
func decodeASN4Capability(buf *bytes.Buffer) (ASN4Capability, error) {
asn4Cap := ASN4Capability{}
fields := []interface{}{
&asn4Cap.ASN4,
}
err := decode(buf, fields)
if err != nil {
return asn4Cap, err
}
return asn4Cap, nil
}
func validateOpen(msg *BGPOpen) error {
if msg.Version != BGP4Version {
return BGPError{
......
......@@ -3,6 +3,7 @@ package packet
import (
"bytes"
"fmt"
"strconv"
"testing"
"github.com/bio-routing/bio-rd/net"
......@@ -70,7 +71,7 @@ func BenchmarkDecodeUpdateMsg(b *testing.B) {
for i := 0; i < b.N; i++ {
buf := bytes.NewBuffer(input)
_, err := decodeUpdateMsg(buf, uint16(len(input)))
_, err := decodeUpdateMsg(buf, uint16(len(input)), &Options{})
if err != nil {
fmt.Printf("decodeUpdateMsg failed: %v\n", err)
}
......@@ -156,7 +157,7 @@ func TestDecode(t *testing.T) {
},
Body: &BGPOpen{
Version: 4,
AS: 200,
ASN: 200,
HoldTime: 15,
BGPIdentifier: uint32(169090600),
OptParmLen: 0,
......@@ -184,7 +185,7 @@ func TestDecode(t *testing.T) {
},
Body: &BGPOpen{
Version: 4,
AS: 200,
ASN: 200,
HoldTime: 15,
BGPIdentifier: uint32(100),
},
......@@ -251,7 +252,7 @@ func TestDecode(t *testing.T) {
for _, test := range tests {
buf := bytes.NewBuffer(test.input)
msg, err := Decode(buf)
msg, err := Decode(buf, &Options{})
if err != nil && !test.wantFail {
t.Errorf("Unexpected error in test %d: %v", test.testNum, err)
......@@ -1369,9 +1370,9 @@ func TestDecodeUpdateMsg(t *testing.T) {
},
{
// 2 withdraws with four path attributes (Communities + AS4Path +AS4Aggregator + Origin), valid update
testNum: 19,
testNum: 20,
input: []byte{0, 5, 8, 10, 16, 192, 168,
0, 30, // Total Path Attribute Length
0, 32, // Total Path Attribute Length
0, // Attribute flags
8, // Attribute Type code (Community)
......@@ -1379,10 +1380,12 @@ func TestDecodeUpdateMsg(t *testing.T) {
0, 0, 1, 0, // Arbitrary Community
0, 0, 1, 1, // Arbitrary Community
128, // Attribute flags
17, // Attribute Type code (AS4Path)
4, // Length
0, 0, 2, 3, // Arbitrary Bytes
128, // Attribute flags
17, // Attribute Type code (AS4Path)
6, // Length
2, // AS_SEQUENCE
1, // Number of ASNs
0x00, 0x03, 0x17, 0xf3, // 202739
128, // Attribute flags
18, // Attribute Type code (AS4Aggregator)
......@@ -1406,7 +1409,7 @@ func TestDecodeUpdateMsg(t *testing.T) {
Pfxlen: 16,
},
},
TotalPathAttrLen: 30,
TotalPathAttrLen: 32,
PathAttributes: &PathAttribute{
Optional: false,
Transitive: false,
......@@ -1420,9 +1423,15 @@ func TestDecodeUpdateMsg(t *testing.T) {
Transitive: false,
Partial: false,
ExtendedLength: false,
Length: 4,
Length: 6,
TypeCode: 17,
Value: uint32(515),
Value: ASPath{
ASPathSegment{
Type: 2,
Count: 1,
ASNs: []uint32{202739},
},
},
Next: &PathAttribute{
Optional: true,
Transitive: false,
......@@ -1447,29 +1456,31 @@ func TestDecodeUpdateMsg(t *testing.T) {
},
}
t.Parallel()
for _, test := range tests {
buf := bytes.NewBuffer(test.input)
l := test.explicitLength
if l == 0 {
l = uint16(len(test.input))
}
msg, err := decodeUpdateMsg(buf, l)
t.Run(strconv.Itoa(test.testNum), func(t *testing.T) {
buf := bytes.NewBuffer(test.input)
l := test.explicitLength
if l == 0 {
l = uint16(len(test.input))
}
msg, err := decodeUpdateMsg(buf, l, &Options{})
if err != nil && !test.wantFail {
t.Errorf("Unexpected error in test %d: %v", test.testNum, err)
continue
}
if err != nil && !test.wantFail {
t.Fatalf("Unexpected error in test %d: %v", test.testNum, err)
}
if err == nil && test.wantFail {
t.Errorf("Expected error did not happen in test %d", test.testNum)
continue
}
if err == nil && test.wantFail {
t.Fatalf("Expected error did not happen in test %d", test.testNum)
}
if err != nil && test.wantFail {
continue
}
if err != nil && test.wantFail {
return
}
assert.Equalf(t, test.expected, msg, "%d", test.testNum)
assert.Equalf(t, test.expected, msg, "%d", test.testNum)
})
}
}
......@@ -1490,7 +1501,7 @@ func TestDecodeMsgBody(t *testing.T) {
}
for _, test := range tests {
res, err := decodeMsgBody(test.buffer, test.msgType, test.length)
res, err := decodeMsgBody(test.buffer, test.msgType, test.length, &Options{})
if test.wantFail && err == nil {
t.Errorf("Expected error dit not happen in test %q", test.name)
}
......@@ -1512,7 +1523,7 @@ func TestDecodeOpenMsg(t *testing.T) {
wantFail: false,
expected: &BGPOpen{
Version: 4,
AS: 257,
ASN: 257,
HoldTime: 15,
BGPIdentifier: 169090600,
OptParmLen: 0,
......
......@@ -35,7 +35,7 @@ func SerializeOpenMsg(msg *BGPOpen) []byte {
serializeHeader(buf, openLen, OpenMsg)
buf.WriteByte(msg.Version)
buf.Write(convert.Uint16Byte(msg.AS))
buf.Write(convert.Uint16Byte(msg.ASN))
buf.Write(convert.Uint16Byte(msg.HoldTime))
buf.Write(convert.Uint32Byte(msg.BGPIdentifier))
......@@ -63,7 +63,7 @@ func serializeHeader(buf *bytes.Buffer, length uint16, typ uint8) {
buf.WriteByte(typ)
}
func (b *BGPUpdateAddPath) SerializeUpdate() ([]byte, error) {
func (b *BGPUpdateAddPath) SerializeUpdate(opt *Options) ([]byte, error) {
budget := MaxLen - MinLen
buf := bytes.NewBuffer(nil)
......@@ -78,7 +78,7 @@ func (b *BGPUpdateAddPath) SerializeUpdate() ([]byte, error) {
pathAttributesBuf := bytes.NewBuffer(nil)
for pa := b.PathAttributes; pa != nil; pa = pa.Next {
paLen := int(pa.serialize(pathAttributesBuf))
paLen := int(pa.serialize(pathAttributesBuf, opt))
budget -= paLen
if budget < 0 {
return nil, fmt.Errorf("update too long")
......@@ -122,7 +122,7 @@ func (b *BGPUpdateAddPath) SerializeUpdate() ([]byte, error) {
return buf.Bytes(), nil
}
func (b *BGPUpdate) SerializeUpdate() ([]byte, error) {
func (b *BGPUpdate) SerializeUpdate(opt *Options) ([]byte, error) {
budget := MaxLen - MinLen
buf := bytes.NewBuffer(nil)
......@@ -137,7 +137,7 @@ func (b *BGPUpdate) SerializeUpdate() ([]byte, error) {
pathAttributesBuf := bytes.NewBuffer(nil)
for pa := b.PathAttributes; pa != nil; pa = pa.Next {
paLen := int(pa.serialize(pathAttributesBuf))
paLen := int(pa.serialize(pathAttributesBuf, opt))
budget -= paLen
if budget < 0 {
return nil, fmt.Errorf("update too long")
......
......@@ -70,7 +70,7 @@ func TestSerializeOpenMsg(t *testing.T) {
name: "Valid #1",
input: &BGPOpen{
Version: 4,
AS: 15169,
ASN: 15169,
HoldTime: 120,
BGPIdentifier: convert.Uint32([]byte{100, 111, 120, 130}),
OptParmLen: 0,
......
package packet
type Options struct {
Supports4OctetASN bool
}
......@@ -52,3 +52,11 @@ func (a AddPathCapability) serialize(buf *bytes.Buffer) {
buf.WriteByte(a.SAFI)
buf.WriteByte(a.SendReceive)
}
type ASN4Capability struct {
ASN4 uint32
}
func (a ASN4Capability) serialize(buf *bytes.Buffer) {
buf.Write(convert.Uint32Byte(a.ASN4))
}
......@@ -9,7 +9,7 @@ import (
"github.com/taktv6/tflow2/convert"
)
func decodePathAttrs(buf *bytes.Buffer, tpal uint16) (*PathAttribute, error) {
func decodePathAttrs(buf *bytes.Buffer, tpal uint16, opt *Options) (*PathAttribute, error) {
var ret *PathAttribute
var eol *PathAttribute
var pa *PathAttribute
......@@ -18,7 +18,7 @@ func decodePathAttrs(buf *bytes.Buffer, tpal uint16) (*PathAttribute, error) {
p := uint16(0)
for p < tpal {
pa, consumed, err = decodePathAttr(buf)
pa, consumed, err = decodePathAttr(buf, opt)
if err != nil {
return nil, fmt.Errorf("Unable to decode path attr: %v", err)
}
......@@ -36,7 +36,7 @@ func decodePathAttrs(buf *bytes.Buffer, tpal uint16) (*PathAttribute, error) {
return ret, nil
}
func decodePathAttr(buf *bytes.Buffer) (pa *PathAttribute, consumed uint16, err error) {
func decodePathAttr(buf *bytes.Buffer, opt *Options) (pa *PathAttribute, consumed uint16, err error) {
pa = &PathAttribute{}
err = decodePathAttrFlags(buf, pa)
......@@ -63,9 +63,18 @@ func decodePathAttr(buf *bytes.Buffer) (pa *PathAttribute, consumed uint16, err
return nil, consumed, fmt.Errorf("Failed to decode Origin: %v", err)
}
case ASPathAttr:
if err := pa.decodeASPath(buf); err != nil {
asnLength := uint8(2)
if opt.Supports4OctetASN {
asnLength = 4
}
if err := pa.decodeASPath(buf, asnLength); err != nil {
return nil, consumed, fmt.Errorf("Failed to decode AS Path: %v", err)
}
case AS4PathAttr:
if err := pa.decodeASPath(buf, 4); err != nil {
return nil, consumed, fmt.Errorf("Failed to decode AS4 Path: %v", err)
}
case NextHopAttr:
if err := pa.decodeNextHop(buf); err != nil {
return nil, consumed, fmt.Errorf("Failed to decode Next-Hop: %v", err)
......@@ -88,10 +97,6 @@ func decodePathAttr(buf *bytes.Buffer) (pa *PathAttribute, consumed uint16, err
if err := pa.decodeCommunities(buf); err != nil {
return nil, consumed, fmt.Errorf("Failed to decode Community: %v", err)
}
case AS4PathAttr:
if err := pa.decodeAS4Path(buf); err != nil {
return nil, consumed, fmt.Errorf("Failed to skip not supported AS4Path: %v", err)
}
case AS4AggregatorAttr:
if err := pa.decodeAS4Aggregator(buf); err != nil {
return nil, consumed, fmt.Errorf("Failed to skip not supported AS4Aggregator: %v", err)
......@@ -139,14 +144,11 @@ func (pa *PathAttribute) decodeOrigin(buf *bytes.Buffer) error {
return dumpNBytes(buf, pa.Length-p)
}
func (pa *PathAttribute) decodeASPath(buf *bytes.Buffer) error {
func (pa *PathAttribute) decodeASPath(buf *bytes.Buffer, asnLength uint8) error {
pa.Value = make(ASPath, 0)
p := uint16(0)
for p < pa.Length {
segment := ASPathSegment{
ASNs: make([]uint32, 0),
}
segment := ASPathSegment{}
err := decode(buf, []interface{}{&segment.Type, &segment.Count})
if err != nil {
......@@ -162,23 +164,51 @@ func (pa *PathAttribute) decodeASPath(buf *bytes.Buffer) error {
return fmt.Errorf("Invalid AS Path segment length: %d", segment.Count)
}
segment.ASNs = make([]uint32, segment.Count)
for i := uint8(0); i < segment.Count; i++ {
asn := uint16(0)
err := decode(buf, []interface{}{&asn})
asn, err := pa.decodeASN(buf, asnLength)
if err != nil {
return err
}
p += 2
p += uint16(asnLength)
segment.ASNs = append(segment.ASNs, uint32(asn))
segment.ASNs[i] = asn
}
pa.Value = append(pa.Value.(ASPath), segment)
}
return nil
}
func (pa *PathAttribute) decodeASN(buf *bytes.Buffer, asnSize uint8) (asn uint32, err error) {
if asnSize == 4 {
return pa.decode4ByteASN(buf)
}
return pa.decode2ByteASN(buf)
}
func (pa *PathAttribute) decode4ByteASN(buf *bytes.Buffer) (asn uint32, err error) {
asn4 := uint32(0)
err = decode(buf, []interface{}{&asn4})
if err != nil {
return 0, err
}
return uint32(asn4), nil
}
func (pa *PathAttribute) decode2ByteASN(buf *bytes.Buffer) (asn uint32, err error) {
asn4 := uint16(0)
err = decode(buf, []interface{}{&asn4})
if err != nil {
return 0, err
}
return uint32(asn4), nil
}
func (pa *PathAttribute) decodeNextHop(buf *bytes.Buffer) error {
return pa.decodeUint32(buf, "next hop")
}
......@@ -273,10 +303,6 @@ func (pa *PathAttribute) decodeLargeCommunities(buf *bytes.Buffer) error {
return nil
}
func (pa *PathAttribute) decodeAS4Path(buf *bytes.Buffer) error {
return pa.decodeUint32(buf, "AS4Path")
}
func (pa *PathAttribute) decodeAS4Aggregator(buf *bytes.Buffer) error {
return pa.decodeUint32(buf, "AS4Aggregator")
}
......@@ -383,14 +409,14 @@ func dumpNBytes(buf *bytes.Buffer, n uint16) error {
return nil
}
func (pa *PathAttribute) serialize(buf *bytes.Buffer) uint8 {
func (pa *PathAttribute) serialize(buf *bytes.Buffer, opt *Options) uint8 {
pathAttrLen := uint8(0)
switch pa.TypeCode {
case OriginAttr:
pathAttrLen = pa.serializeOrigin(buf)
case ASPathAttr:
pathAttrLen = pa.serializeASPath(buf)
pathAttrLen = pa.serializeASPath(buf, opt)
case NextHopAttr:
pathAttrLen = pa.serializeNextHop(buf)
case MEDAttr:
......@@ -421,21 +447,32 @@ func (pa *PathAttribute) serializeOrigin(buf *bytes.Buffer) uint8 {
return 4
}
func (pa *PathAttribute) serializeASPath(buf *bytes.Buffer) uint8 {
func (pa *PathAttribute) serializeASPath(buf *bytes.Buffer, opt *Options) uint8 {
attrFlags := uint8(0)
attrFlags = setTransitive(attrFlags)
buf.WriteByte(attrFlags)
buf.WriteByte(ASPathAttr)
asnLength := uint8(2)
if opt.Supports4OctetASN {
asnLength = 4
}
length := uint8(0)
segmentsBuf := bytes.NewBuffer(nil)
for _, segment := range pa.Value.(ASPath) {
segmentsBuf.WriteByte(segment.Type)
segmentsBuf.WriteByte(uint8(len(segment.ASNs)))
for _, asn := range segment.ASNs {
segmentsBuf.Write(convert.Uint16Byte(uint16(asn)))
if asnLength == 2 {
segmentsBuf.Write(convert.Uint16Byte(uint16(asn)))
} else {
segmentsBuf.Write(convert.Uint32Byte(asn))
}
}
length += 2 + uint8(len(segment.ASNs))*2
fmt.Println(segment.ASNs)
length += 2 + uint8(len(segment.ASNs))*asnLength
}
buf.WriteByte(length)
......
......@@ -50,7 +50,7 @@ func TestDecodePathAttrs(t *testing.T) {
}
for _, test := range tests {
res, err := decodePathAttrs(bytes.NewBuffer(test.input), uint16(len(test.input)))
res, err := decodePathAttrs(bytes.NewBuffer(test.input), uint16(len(test.input)), &Options{})
if test.wantFail && err == nil {
t.Errorf("Expected error did not happen for test %q", test.name)
......@@ -173,7 +173,7 @@ func TestDecodePathAttr(t *testing.T) {
}
for _, test := range tests {
res, _, err := decodePathAttr(bytes.NewBuffer(test.input))
res, _, err := decodePathAttr(bytes.NewBuffer(test.input), &Options{})
if test.wantFail && err == nil {
t.Errorf("Expected error did not happen for test %q", test.name)
......@@ -264,6 +264,7 @@ func TestDecodeASPath(t *testing.T) {
input []byte
wantFail bool
explicitLength uint16
use4OctetASNs bool
expected *PathAttribute
}{
{
......@@ -308,6 +309,28 @@ func TestDecodeASPath(t *testing.T) {
},
},
},
{
name: "32 bit ASNs in AS_PATH",
input: []byte{
1, // AS_SEQUENCE
3, // Path Length
0, 0, 0, 100, 0, 0, 0, 222, 0, 0, 0, 240,
},
wantFail: false,
use4OctetASNs: true,
expected: &PathAttribute{
Length: 14,
Value: ASPath{
ASPathSegment{
Type: 1,
Count: 3,
ASNs: []uint32{
100, 222, 240,
},
},
},
},
},
{
name: "Empty input",
input: []byte{},
......@@ -326,28 +349,36 @@ func TestDecodeASPath(t *testing.T) {
}
for _, test := range tests {
l := uint16(len(test.input))
if test.explicitLength != 0 {
l = test.explicitLength
}
pa := &PathAttribute{
Length: l,
}
err := pa.decodeASPath(bytes.NewBuffer(test.input))
t.Run(test.name, func(t *testing.T) {
l := uint16(len(test.input))
if test.explicitLength != 0 {
l = test.explicitLength
}
pa := &PathAttribute{
Length: l,
}
if test.wantFail && err == nil {
t.Errorf("Expected error did not happen for test %q", test.name)
}
asnLength := uint8(2)
if test.use4OctetASNs {
asnLength = 4
}
if !test.wantFail && err != nil {
t.Errorf("Unexpected failure for test %q: %v", test.name, err)
}
err := pa.decodeASPath(bytes.NewBuffer(test.input), asnLength)
if err != nil {
continue
}
if test.wantFail && err == nil {
t.Errorf("Expected error did not happen for test %q", test.name)
}
assert.Equal(t, test.expected, pa)
if !test.wantFail && err != nil {
t.Errorf("Unexpected failure for test %q: %v", test.name, err)
}
if err != nil {
return
}
assert.Equal(t, test.expected, pa)
})
}
}
......@@ -1239,6 +1270,7 @@ func TestSerializeASPath(t *testing.T) {
input *PathAttribute
expected []byte
expectedLen uint8
use32BitASN bool
}{
{
name: "Test #1",
......@@ -1265,17 +1297,49 @@ func TestSerializeASPath(t *testing.T) {
},
expectedLen: 10,
},
{
name: "32bit ASN",
input: &PathAttribute{
TypeCode: ASPathAttr,
Value: ASPath{
{
Type: 2, // Sequence
ASNs: []uint32{
100, 200, 210,
},
},
},
},
expected: []byte{
64, // Attribute flags
2, // Type
14, // Length
2, // AS_SEQUENCE
3, // ASN count
0, 0, 0, 100, // ASN 100
0, 0, 0, 200, // ASN 200
0, 0, 0, 210, // ASN 210
},
expectedLen: 16,
use32BitASN: true,
},
}
t.Parallel()
for _, test := range tests {
buf := bytes.NewBuffer(nil)
n := test.input.serializeASPath(buf)
if n != test.expectedLen {
t.Errorf("Unexpected length for test %q: %d", test.name, n)
continue
}
t.Run(test.name, func(t *testing.T) {
buf := bytes.NewBuffer(nil)
opt := &Options{
Supports4OctetASN: test.use32BitASN,
}
n := test.input.serializeASPath(buf, opt)
if n != test.expectedLen {
t.Fatalf("Unexpected length for test %q: %d", test.name, n)
}
assert.Equal(t, test.expected, buf.Bytes())
assert.Equal(t, test.expected, buf.Bytes())
})
}
}
......@@ -1561,7 +1625,8 @@ func TestSerialize(t *testing.T) {
}
for _, test := range tests {
res, err := test.msg.SerializeUpdate()
opt := &Options{}
res, err := test.msg.SerializeUpdate(opt)
if err != nil {
if test.wantFail {
continue
......@@ -1767,7 +1832,8 @@ func TestSerializeAddPath(t *testing.T) {
}
for _, test := range tests {
res, err := test.msg.SerializeUpdate()
opt := &Options{}
res, err := test.msg.SerializeUpdate(opt)
if err != nil {
if test.wantFail {
continue
......
......@@ -33,6 +33,7 @@ go_library(
"//routingtable/adjRIBIn:go_default_library",
"//routingtable/adjRIBOut:go_default_library",
"//routingtable/filter:go_default_library",
"//routingtable/locRIB:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
],
)
......@@ -40,6 +41,8 @@ go_library(
go_test(
name = "go_default_test",
srcs = [
"fsm_open_sent_test.go",
"fsm_test.go",
"server_test.go",
"update_helper_test.go",
"withdraw_test.go",
......
......@@ -8,6 +8,7 @@ import (
"github.com/bio-routing/bio-rd/protocols/bgp/packet"
"github.com/bio-routing/bio-rd/routingtable"
"github.com/bio-routing/bio-rd/routingtable/locRIB"
log "github.com/sirupsen/logrus"
)
......@@ -56,12 +57,14 @@ type FSM struct {
capAddPathSend bool
capAddPathRecv bool
options *packet.Options
local net.IP
ribsInitialized bool
adjRIBIn routingtable.RouteTableClient
adjRIBOut routingtable.RouteTableClient
rib routingtable.RouteTableClient
rib *locRIB.LocRIB
updateSender routingtable.RouteTableClient
neighborID uint32
......@@ -99,6 +102,7 @@ func newFSM2(peer *peer) *FSM {
msgRecvFailCh: make(chan error),
stopMsgRecvCh: make(chan struct{}),
rib: peer.rib,
options: &packet.Options{},
}
}
......@@ -219,13 +223,7 @@ func (fsm *FSM) resetConnectRetryCounter() {
}
func (fsm *FSM) sendOpen() error {
msg := packet.SerializeOpenMsg(&packet.BGPOpen{
Version: BGPVersion,
AS: uint16(fsm.peer.localASN),
HoldTime: uint16(fsm.peer.holdTime / time.Second),
BGPIdentifier: fsm.peer.server.routerID,
OptParams: fsm.peer.optOpenParams,
})
msg := packet.SerializeOpenMsg(fsm.openMessage())
_, err := fsm.con.Write(msg)
if err != nil {
......@@ -235,6 +233,24 @@ func (fsm *FSM) sendOpen() error {
return nil
}
func (fsm *FSM) openMessage() *packet.BGPOpen {
return &packet.BGPOpen{
Version: BGPVersion,
ASN: fsm.local16BitASN(),
HoldTime: uint16(fsm.peer.holdTime / time.Second),
BGPIdentifier: fsm.peer.routerID,
OptParams: fsm.peer.optOpenParams,
}
}
func (fsm *FSM) local16BitASN() uint16 {
if fsm.peer.localASN > uint32(^uint16(0)) {
return packet.ASTransASN
}
return uint16(fsm.peer.localASN)
}
func (fsm *FSM) sendNotification(errorCode uint8, errorSubCode uint8) error {
msg := packet.SerializeNotificationMsg(&packet.BGPNotification{})
......
......@@ -55,7 +55,10 @@ func (s establishedState) run() (state, string) {
}
func (s *establishedState) init() error {
s.fsm.adjRIBIn = adjRIBIn.New(s.fsm.peer.importFilter)
contributingASNs := s.fsm.rib.GetContributingASNs()
s.fsm.adjRIBIn = adjRIBIn.New(s.fsm.peer.importFilter, contributingASNs)
contributingASNs.Add(s.fsm.peer.localASN)
s.fsm.adjRIBIn.Register(s.fsm.rib)
host, _, err := net.SplitHostPort(s.fsm.con.LocalAddr().String())
......@@ -96,6 +99,7 @@ func (s *establishedState) init() error {
}
func (s *establishedState) uninit() {
s.fsm.rib.GetContributingASNs().Remove(s.fsm.peer.localASN)
s.fsm.adjRIBIn.Unregister(s.fsm.rib)
s.fsm.rib.Unregister(s.fsm.adjRIBOut)
s.fsm.adjRIBOut.Unregister(s.fsm.updateSender)
......@@ -154,7 +158,7 @@ func (s *establishedState) keepaliveTimerExpired() (state, string) {
}
func (s *establishedState) msgReceived(data []byte) (state, string) {
msg, err := packet.Decode(bytes.NewBuffer(data))
msg, err := packet.Decode(bytes.NewBuffer(data), s.fsm.options)
if err != nil {
switch bgperr := err.(type) {
case packet.BGPError:
......
......@@ -82,7 +82,7 @@ func (s *openConfirmState) keepaliveTimerExpired() (state, string) {
}
func (s *openConfirmState) msgReceived(data []byte) (state, string) {
msg, err := packet.Decode(bytes.NewBuffer(data))
msg, err := packet.Decode(bytes.NewBuffer(data), s.fsm.options)
if err != nil {
switch bgperr := err.(type) {
case packet.BGPError:
......
......@@ -10,7 +10,8 @@ import (
)
type openSentState struct {
fsm *FSM
fsm *FSM
peerASNRcvd uint32
}
func newOpenSentState(fsm *FSM) *openSentState {
......@@ -73,7 +74,7 @@ func (s *openSentState) holdTimerExpired() (state, string) {
}
func (s *openSentState) msgReceived(data []byte) (state, string) {
msg, err := packet.Decode(bytes.NewBuffer(data))
msg, err := packet.Decode(bytes.NewBuffer(data), s.fsm.options)
if err != nil {
switch bgperr := err.(type) {
case packet.BGPError:
......@@ -104,6 +105,8 @@ func (s *openSentState) unexpectedMessage() (state, string) {
func (s *openSentState) openMsgReceived(msg *packet.BGPMessage) (state, string) {
openMsg := msg.Body.(*packet.BGPOpen)
s.peerASNRcvd = uint32(openMsg.ASN)
s.fsm.neighborID = openMsg.BGPIdentifier
stopTimer(s.fsm.connectRetryTimer)
if s.fsm.peer.collisionHandling(s.fsm) {
......@@ -114,6 +117,10 @@ func (s *openSentState) openMsgReceived(msg *packet.BGPMessage) (state, string)
return s.tcpFailure()
}
return s.handleOpenMessage(openMsg)
}
func (s *openSentState) handleOpenMessage(openMsg *packet.BGPOpen) (state, string) {
s.fsm.holdTime = time.Duration(math.Min(float64(s.fsm.peer.holdTime), float64(time.Duration(openMsg.HoldTime)*time.Second)))
if s.fsm.holdTime != 0 {
if !s.fsm.holdTimer.Reset(s.fsm.holdTime) {
......@@ -123,7 +130,13 @@ func (s *openSentState) openMsgReceived(msg *packet.BGPMessage) (state, string)
s.fsm.keepaliveTimer = time.NewTimer(s.fsm.keepaliveTime)
}
s.peerASNRcvd = uint32(openMsg.ASN)
s.processOpenOptions(openMsg.OptParams)
if s.peerASNRcvd != s.fsm.peer.peerASN {
return newCeaseState(), fmt.Sprintf("Expected session from %d, got open message with ASN %d", s.fsm.peer.peerASN, s.peerASNRcvd)
}
return newOpenConfirmState(s.fsm), "Received OPEN message"
}
......@@ -153,7 +166,8 @@ func (s *openSentState) processCapability(cap packet.Capability) {
switch cap.Code {
case packet.AddPathCapabilityCode:
s.processAddPathCapability(cap.Value.(packet.AddPathCapability))
case packet.ASN4CapabilityCode:
s.processASN4Capability(cap.Value.(packet.ASN4Capability))
}
}
......@@ -184,6 +198,14 @@ func (s *openSentState) processAddPathCapability(addPathCap packet.AddPathCapabi
}
}
func (s *openSentState) processASN4Capability(cap packet.ASN4Capability) {
s.fsm.options.Supports4OctetASN = true
if s.peerASNRcvd == packet.ASTransASN {
s.peerASNRcvd = cap.ASN4
}
}
func (s *openSentState) notification(msg *packet.BGPMessage) (state, string) {
stopTimer(s.fsm.connectRetryTimer)
s.fsm.con.Close()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment