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

Merge branch 'master' into feature/unknown_attr_pass

parents e4fb787b 41f347aa
No related branches found
No related tags found
No related merge requests found
Showing
with 316 additions and 81 deletions
...@@ -69,7 +69,7 @@ func (pfx Prefix) Contains(x Prefix) bool { ...@@ -69,7 +69,7 @@ func (pfx Prefix) Contains(x Prefix) bool {
return false return false
} }
mask := (uint32(1) << (32 - pfx.pfxlen)) mask := uint32((math.MaxUint32 << (32 - pfx.pfxlen)))
return (pfx.addr & mask) == (x.addr & mask) return (pfx.addr & mask) == (x.addr & mask)
} }
......
...@@ -179,6 +179,18 @@ func TestContains(t *testing.T) { ...@@ -179,6 +179,18 @@ func TestContains(t *testing.T) {
}, },
expected: false, expected: false,
}, },
{
name: "Test 7",
a: Prefix{
addr: strAddr("169.0.0.0"),
pfxlen: 25,
},
b: Prefix{
addr: strAddr("169.1.1.0"),
pfxlen: 26,
},
expected: false,
},
} }
for _, test := range tests { for _, test := range tests {
...@@ -332,3 +344,8 @@ func TestStrToAddr(t *testing.T) { ...@@ -332,3 +344,8 @@ func TestStrToAddr(t *testing.T) {
assert.Equal(t, test.expected, res) assert.Equal(t, test.expected, res)
} }
} }
func strAddr(s string) uint32 {
ret, _ := StrToAddr(s)
return ret
}
...@@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") ...@@ -3,6 +3,7 @@ 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 = [
"fake_conn.go",
"fsm.go", "fsm.go",
"fsm_active.go", "fsm_active.go",
"fsm_cease.go", "fsm_cease.go",
......
package server
import (
"net"
"time"
)
type fakeConn struct {
}
type fakeAddr struct {
}
func (f fakeAddr) Network() string {
return ""
}
func (f fakeAddr) String() string {
return "169.254.100.100:179"
}
func (f fakeConn) Read(b []byte) (n int, err error) {
return 0, nil
}
func (f fakeConn) Write(b []byte) (n int, err error) {
return len(b), nil
}
func (f fakeConn) Close() error {
return nil
}
func (f fakeConn) LocalAddr() net.Addr {
return fakeAddr{}
}
func (f fakeConn) RemoteAddr() net.Addr {
return fakeAddr{}
}
func (f fakeConn) SetDeadline(t time.Time) error {
return nil
}
func (f fakeConn) SetReadDeadline(t time.Time) error {
return nil
}
func (f fakeConn) SetWriteDeadline(t time.Time) error {
return nil
}
package server package server
import ( import (
"net"
"sync"
"testing" "testing"
"time" "time"
"github.com/bio-routing/bio-rd/protocols/bgp/packet" "github.com/bio-routing/bio-rd/protocols/bgp/packet"
"github.com/bio-routing/bio-rd/routingtable/filter"
"github.com/bio-routing/bio-rd/routingtable/locRIB"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
// TestFSM100Updates emulates receiving 100 BGP updates and withdraws. Checks route counts.
func TestFSM100Updates(t *testing.T) {
fsmA := newFSM2(&peer{
addr: net.ParseIP("169.254.100.100"),
rib: locRIB.New(),
importFilter: filter.NewAcceptAllFilter(),
exportFilter: filter.NewAcceptAllFilter(),
})
fsmA.holdTimer = time.NewTimer(time.Second * 90)
fsmA.keepaliveTimer = time.NewTimer(time.Second * 30)
fsmA.connectRetryTimer = time.NewTimer(time.Second * 120)
fsmA.state = newEstablishedState(fsmA)
var wg sync.WaitGroup
wg.Add(1)
go func() {
fsmA.con = fakeConn{}
for {
nextState, reason := fsmA.state.run()
fsmA.state = nextState
stateName := stateName(nextState)
switch stateName {
case "idle":
wg.Done()
return
case "cease":
t.Errorf("Unexpected cease state: %s", reason)
wg.Done()
return
case "established":
continue
default:
t.Errorf("Unexpected new state: %s", reason)
wg.Done()
return
}
}
}()
for i := uint8(0); i < 255; i++ {
a := i % 10
b := i % 8
update := []byte{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
0, 54,
2,
0, 0,
0, 26,
64, // Attribute flags
1, // Attribute Type code (ORIGIN)
1, // Length
2, // INCOMPLETE
64, // Attribute flags
2, // Attribute Type code (AS Path)
12, // Length
2, // Type = AS_SEQUENCE
2, // Path Segement Length
59, 65, // AS15169
12, 248, // AS3320
1, // Type = AS_SET
2, // Path Segement Length
59, 65, // AS15169
12, 248, // AS3320
0, // Attribute flags
3, // Attribute Type code (Next Hop)
4, // Length
10, 11, 12, 13, // Next Hop
b + 25, 169, a, i, 0,
}
fsmA.msgRecvCh <- update
}
time.Sleep(time.Second)
ribRouteCount := fsmA.rib.RouteCount()
if ribRouteCount != 255 {
t.Errorf("Unexpected route count in LocRIB: %d", ribRouteCount)
}
for i := uint8(0); i < 255; i++ {
a := i % 10
b := i % 8
update := []byte{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
0, 28,
2,
0, 5,
b + 25, 169, a, i, 0,
0, 0,
}
fsmA.msgRecvCh <- update
ribRouteCount = fsmA.rib.RouteCount()
}
time.Sleep(time.Second * 1)
ribRouteCount = fsmA.rib.RouteCount()
if ribRouteCount != 0 {
t.Errorf("Unexpected route count in LocRIB: %d", ribRouteCount)
}
fsmA.eventCh <- ManualStop
wg.Wait()
}
func TestOpenMessage(t *testing.T) { func TestOpenMessage(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
......
...@@ -57,6 +57,12 @@ func (u *UpdateSender) UpdateNewClient(client routingtable.RouteTableClient) err ...@@ -57,6 +57,12 @@ func (u *UpdateSender) UpdateNewClient(client routingtable.RouteTableClient) err
return nil return nil
} }
// RouteCount does nothing
func (u *UpdateSender) RouteCount() int64 {
log.Warningf("BGP Update Sender: RouteCount() not supported")
return 0
}
func asPathString(iBGP bool, localASN uint16, asPath string) string { func asPathString(iBGP bool, localASN uint16, asPath string) string {
ret := "" ret := ""
if iBGP { if iBGP {
......
...@@ -53,3 +53,9 @@ func (u *UpdateSenderAddPath) UpdateNewClient(client routingtable.RouteTableClie ...@@ -53,3 +53,9 @@ func (u *UpdateSenderAddPath) UpdateNewClient(client routingtable.RouteTableClie
log.Warningf("BGP Update Sender: UpdateNewClient not implemented") log.Warningf("BGP Update Sender: UpdateNewClient not implemented")
return nil return nil
} }
// RouteCount returns the number of stored routes
func (u *UpdateSenderAddPath) RouteCount() int64 {
log.Warningf("BGP Update Sender: RouteCount not implemented")
return 0
}
...@@ -54,6 +54,11 @@ func (a *AdjRIBIn) UpdateNewClient(client routingtable.RouteTableClient) error { ...@@ -54,6 +54,11 @@ func (a *AdjRIBIn) UpdateNewClient(client routingtable.RouteTableClient) error {
return nil return nil
} }
// RouteCount returns the number of stored routes
func (a *AdjRIBIn) RouteCount() int64 {
return a.rt.GetRouteCount()
}
// AddPath replaces the path for prefix `pfx`. If the prefix doesn't exist it is added. // AddPath replaces the path for prefix `pfx`. If the prefix doesn't exist it is added.
func (a *AdjRIBIn) AddPath(pfx net.Prefix, p *route.Path) error { func (a *AdjRIBIn) AddPath(pfx net.Prefix, p *route.Path) error {
a.mu.Lock() a.mu.Lock()
......
load("@io_bazel_rules_go//go:def.bzl", "go_library") load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
...@@ -16,3 +16,13 @@ go_library( ...@@ -16,3 +16,13 @@ go_library(
"//vendor/github.com/sirupsen/logrus:go_default_library", "//vendor/github.com/sirupsen/logrus:go_default_library",
], ],
) )
go_test(
name = "go_default_test",
srcs = ["path_id_manager_test.go"],
embed = [":go_default_library"],
deps = [
"//route:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
],
)
...@@ -39,6 +39,11 @@ func (a *AdjRIBOut) UpdateNewClient(client routingtable.RouteTableClient) error ...@@ -39,6 +39,11 @@ func (a *AdjRIBOut) UpdateNewClient(client routingtable.RouteTableClient) error
return nil return nil
} }
// RouteCount returns the number of stored routes
func (a *AdjRIBOut) RouteCount() int64 {
return a.rt.GetRouteCount()
}
// AddPath adds path p to prefix `pfx` // AddPath adds path p to prefix `pfx`
func (a *AdjRIBOut) AddPath(pfx bnet.Prefix, p *route.Path) error { func (a *AdjRIBOut) AddPath(pfx bnet.Prefix, p *route.Path) error {
if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) { if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
......
...@@ -55,104 +55,96 @@ X: ...@@ -55,104 +55,96 @@ X:
func TestReleasePath(t *testing.T) { func TestReleasePath(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
pm *pathIDManager adds []*route.Path
release *route.Path release *route.Path
expected *pathIDManager expected []*route.Path
wantFail bool wantFail bool
}{ }{
{ {
name: "Release existent", name: "Release existent",
pm: &pathIDManager{ adds: []*route.Path{
ids: map[uint32]uint64{ {
0: 1, BGPPath: &route.BGPPath{
1: 1,
2: 1,
},
idByPath: map[route.BGPPath]uint32{
route.BGPPath{
LocalPref: 0, LocalPref: 0,
}: 0, },
route.BGPPath{ },
{
BGPPath: &route.BGPPath{
LocalPref: 1, LocalPref: 1,
}: 1, },
route.BGPPath{ },
{
BGPPath: &route.BGPPath{
LocalPref: 2, LocalPref: 2,
}: 2, },
}, },
last: 2,
used: 3,
}, },
release: &route.Path{BGPPath: &route.BGPPath{ release: &route.Path{BGPPath: &route.BGPPath{
LocalPref: 2, LocalPref: 2,
}}, }},
expected: &pathIDManager{ expected: []*route.Path{
ids: map[uint32]uint64{ {
0: 1, BGPPath: &route.BGPPath{
1: 1,
},
idByPath: map[route.BGPPath]uint32{
route.BGPPath{
LocalPref: 0, LocalPref: 0,
}: 0, },
route.BGPPath{ },
{
BGPPath: &route.BGPPath{
LocalPref: 1, LocalPref: 1,
}: 1, },
}, },
last: 2,
used: 2,
}, },
}, },
{ {
name: "Release non-existent", name: "Release non-existent",
pm: &pathIDManager{ adds: []*route.Path{
ids: map[uint32]uint64{ {
0: 1, BGPPath: &route.BGPPath{
1: 1,
2: 1,
},
idByPath: map[route.BGPPath]uint32{
route.BGPPath{
LocalPref: 0, LocalPref: 0,
}: 0, },
route.BGPPath{ },
{
BGPPath: &route.BGPPath{
LocalPref: 1, LocalPref: 1,
}: 1, },
route.BGPPath{ },
{
BGPPath: &route.BGPPath{
LocalPref: 2, LocalPref: 2,
}: 2, },
}, },
last: 2,
used: 3,
}, },
release: &route.Path{BGPPath: &route.BGPPath{ release: &route.Path{BGPPath: &route.BGPPath{
LocalPref: 4, LocalPref: 5,
}}, }},
expected: &pathIDManager{ expected: []*route.Path{
ids: map[uint32]uint64{ {
0: 1, BGPPath: &route.BGPPath{
1: 1,
2: 1,
},
idByPath: map[route.BGPPath]uint32{
route.BGPPath{
LocalPref: 0, LocalPref: 0,
}: 0, },
route.BGPPath{ },
{
BGPPath: &route.BGPPath{
LocalPref: 1, LocalPref: 1,
}: 1, },
route.BGPPath{ },
{
BGPPath: &route.BGPPath{
LocalPref: 2, LocalPref: 2,
}: 2, },
}, },
last: 2,
used: 3,
}, },
wantFail: true, wantFail: true,
}, },
} }
for _, test := range tests { for _, test := range tests {
_, err := test.pm.releasePath(test.release) pm := newPathIDManager()
for _, add := range test.adds {
pm.addPath(add)
}
_, err := pm.releasePath(test.release)
if err != nil { if err != nil {
if test.wantFail { if test.wantFail {
continue continue
...@@ -167,7 +159,12 @@ func TestReleasePath(t *testing.T) { ...@@ -167,7 +159,12 @@ func TestReleasePath(t *testing.T) {
continue continue
} }
assert.Equalf(t, test.expected, test.pm, "%s", test.name) expectedPM := newPathIDManager()
for _, x := range test.expected {
expectedPM.addPath(x)
}
expectedPM.last++
assert.Equalf(t, expectedPM, pm, "%s", test.name)
} }
} }
...@@ -13,4 +13,5 @@ type RouteTableClient interface { ...@@ -13,4 +13,5 @@ type RouteTableClient interface {
Register(RouteTableClient) Register(RouteTableClient)
RegisterWithOptions(RouteTableClient, ClientOptions) RegisterWithOptions(RouteTableClient, ClientOptions)
Unregister(RouteTableClient) Unregister(RouteTableClient)
RouteCount() int64
} }
...@@ -34,6 +34,10 @@ func (m MockClient) Unregister(RouteTableClient) { ...@@ -34,6 +34,10 @@ func (m MockClient) Unregister(RouteTableClient) {
return return
} }
func (m MockClient) RouteCount() int64 {
return 0
}
func TestClients(t *testing.T) { func TestClients(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
......
...@@ -34,7 +34,7 @@ func TestInRange(t *testing.T) { ...@@ -34,7 +34,7 @@ func TestInRange(t *testing.T) {
}, },
{ {
name: "matches end of range (22-24)", name: "matches end of range (22-24)",
prefix: net.NewPfx(strAddr("1.2.128.0"), 24), prefix: net.NewPfx(strAddr("1.2.3.0"), 24),
pattern: net.NewPfx(strAddr("1.2.0.0"), 22), pattern: net.NewPfx(strAddr("1.2.0.0"), 22),
begin: 22, begin: 22,
end: 24, end: 24,
......
...@@ -55,6 +55,11 @@ func (a *LocRIB) UpdateNewClient(client routingtable.RouteTableClient) error { ...@@ -55,6 +55,11 @@ func (a *LocRIB) UpdateNewClient(client routingtable.RouteTableClient) error {
return nil return nil
} }
// RouteCount returns the number of stored routes
func (a *LocRIB) RouteCount() int64 {
return a.rt.GetRouteCount()
}
// AddPath replaces the path for prefix `pfx`. If the prefix doesn't exist it is added. // AddPath replaces the path for prefix `pfx`. If the prefix doesn't exist it is added.
func (a *LocRIB) AddPath(pfx net.Prefix, p *route.Path) error { func (a *LocRIB) AddPath(pfx net.Prefix, p *route.Path) error {
a.mu.Lock() a.mu.Lock()
......
...@@ -50,3 +50,7 @@ func (m *RTMockClient) RemovePath(pfx net.Prefix, p *route.Path) bool { ...@@ -50,3 +50,7 @@ func (m *RTMockClient) RemovePath(pfx net.Prefix, p *route.Path) bool {
m.removePathParams.Path = p m.removePathParams.Path = p
return true return true
} }
func (m *RTMockClient) RouteCount() int64 {
return 0
}
...@@ -40,7 +40,11 @@ func (rt *RoutingTable) addPath(pfx net.Prefix, p *route.Path) error { ...@@ -40,7 +40,11 @@ func (rt *RoutingTable) addPath(pfx net.Prefix, p *route.Path) error {
return nil return nil
} }
rt.root = rt.root.addPath(pfx, p) root, isNew := rt.root.addPath(pfx, p)
rt.root = root
if isNew {
atomic.AddInt64(&rt.routeCount, 1)
}
return nil return nil
} }
......
...@@ -118,47 +118,50 @@ func (n *node) get(pfx net.Prefix) *node { ...@@ -118,47 +118,50 @@ func (n *node) get(pfx net.Prefix) *node {
return n.h.get(pfx) return n.h.get(pfx)
} }
func (n *node) addPath(pfx net.Prefix, p *route.Path) *node { func (n *node) addPath(pfx net.Prefix, p *route.Path) (*node, bool) {
currentPfx := n.route.Prefix() currentPfx := n.route.Prefix()
if currentPfx == pfx { if currentPfx == pfx {
n.route.AddPath(p) n.route.AddPath(p)
n.dummy = false n.dummy = false
return n return n, true
} }
// is pfx NOT a subnet of this node? // is pfx NOT a subnet of this node?
if !currentPfx.Contains(pfx) { if !currentPfx.Contains(pfx) {
if pfx.Contains(currentPfx) { if pfx.Contains(currentPfx) {
return n.insertBefore(pfx, p, n.route.Pfxlen()-n.skip-1) return n.insertBefore(pfx, p, n.route.Pfxlen()-n.skip-1), true
} }
return n.newSuperNode(pfx, p) return n.newSuperNode(pfx, p), true
} }
// pfx is a subnet of this node // pfx is a subnet of this node
b := getBitUint32(pfx.Addr(), n.route.Pfxlen()+1) b := getBitUint32(pfx.Addr(), n.route.Pfxlen()+1)
if !b { if !b {
return n.insertLow(pfx, p, currentPfx.Pfxlen()) return n.insertLow(pfx, p, currentPfx.Pfxlen())
} }
return n.insertHigh(pfx, p, n.route.Pfxlen()) return n.insertHigh(pfx, p, n.route.Pfxlen())
} }
func (n *node) insertLow(pfx net.Prefix, p *route.Path, parentPfxLen uint8) *node { func (n *node) insertLow(pfx net.Prefix, p *route.Path, parentPfxLen uint8) (*node, bool) {
if n.l == nil { if n.l == nil {
n.l = newNode(pfx, p, pfx.Pfxlen()-parentPfxLen-1, false) n.l = newNode(pfx, p, pfx.Pfxlen()-parentPfxLen-1, false)
return n return n, true
} }
n.l = n.l.addPath(pfx, p) newRoot, isNew := n.l.addPath(pfx, p)
return n n.l = newRoot
return n, isNew
} }
func (n *node) insertHigh(pfx net.Prefix, p *route.Path, parentPfxLen uint8) *node { func (n *node) insertHigh(pfx net.Prefix, p *route.Path, parentPfxLen uint8) (*node, bool) {
if n.h == nil { if n.h == nil {
n.h = newNode(pfx, p, pfx.Pfxlen()-parentPfxLen-1, false) n.h = newNode(pfx, p, pfx.Pfxlen()-parentPfxLen-1, false)
return n return n, true
} }
n.h = n.h.addPath(pfx, p) newRoot, isNew := n.h.addPath(pfx, p)
return n n.h = newRoot
return n, isNew
} }
func (n *node) newSuperNode(pfx net.Prefix, p *route.Path) *node { func (n *node) newSuperNode(pfx net.Prefix, p *route.Path) *node {
...@@ -223,5 +226,6 @@ func (n *node) dump(res []*route.Route) []*route.Route { ...@@ -223,5 +226,6 @@ func (n *node) dump(res []*route.Route) []*route.Route {
res = n.l.dump(res) res = n.l.dump(res)
res = n.h.dump(res) res = n.h.dump(res)
return res return res
} }
...@@ -13,7 +13,7 @@ go_library( ...@@ -13,7 +13,7 @@ go_library(
"union.go", "union.go",
"version.go", "version.go",
], ],
importmap = "vendor/github.com/Masterminds/semver", importmap = "github.com/bio-routing/bio-rd/vendor/github.com/Masterminds/semver",
importpath = "github.com/Masterminds/semver", importpath = "github.com/Masterminds/semver",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
...@@ -12,7 +12,7 @@ go_library( ...@@ -12,7 +12,7 @@ go_library(
"vcs_local_lookup.go", "vcs_local_lookup.go",
"vcs_remote_lookup.go", "vcs_remote_lookup.go",
], ],
importmap = "vendor/github.com/Masterminds/vcs", importmap = "github.com/bio-routing/bio-rd/vendor/github.com/Masterminds/vcs",
importpath = "github.com/Masterminds/vcs", importpath = "github.com/Masterminds/vcs",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment