Skip to content
Snippets Groups Projects
Commit 6c91410c authored by Christoph Petrausch's avatar Christoph Petrausch Committed by Daniel Czerwonk
Browse files

Feature: Add function to check if localRIB contains a given path and prefix combination. (#11)

* Add a ContainsPfxPath method to LocRIB to check if a route exists already.
* Check for nil pathes in compare
* Add myself to CONTRIBUTORS and AUTHORS
* Added docs
* Avoid segfault on nil and remove shaddowing of keyword new
* Make route == nil useful
* Update loc_rib.go
parent feb8f3fa
No related branches found
No related tags found
No related merge requests found
...@@ -13,3 +13,4 @@ ...@@ -13,3 +13,4 @@
Cedric Kienzler Cedric Kienzler
Daniel Czerwonk Daniel Czerwonk
Oliver Herms Oliver Herms
Christoph Petrausch
...@@ -7,3 +7,4 @@ ...@@ -7,3 +7,4 @@
Cedric Kienzler Cedric Kienzler
Daniel Czerwonk Daniel Czerwonk
Oliver Herms Oliver Herms
Christoph Petrausch
\ No newline at end of file
...@@ -10,6 +10,16 @@ type Path struct { ...@@ -10,6 +10,16 @@ type Path struct {
// Compare returns negative if p < q, 0 if paths are equal, positive if p > q // Compare returns negative if p < q, 0 if paths are equal, positive if p > q
func (p *Path) Compare(q *Path) int8 { func (p *Path) Compare(q *Path) int8 {
switch {
case p == nil && q == nil:
return 0
case p == nil:
return -1
case q == nil:
return 1
default:
}
if p.Type > q.Type { if p.Type > q.Type {
return 1 return 1
} }
......
...@@ -45,13 +45,16 @@ func NewRoute(pfx net.Prefix, p *Path) *Route { ...@@ -45,13 +45,16 @@ func NewRoute(pfx net.Prefix, p *Path) *Route {
// Copy returns a copy of route r // Copy returns a copy of route r
func (r *Route) Copy() *Route { func (r *Route) Copy() *Route {
new := &Route{ if r == nil {
return nil
}
n := &Route{
pfx: r.pfx, pfx: r.pfx,
ecmpPaths: r.ecmpPaths, ecmpPaths: r.ecmpPaths,
} }
new.paths = make([]*Path, len(r.paths)) n.paths = make([]*Path, len(r.paths))
copy(new.paths, r.paths) copy(n.paths, r.paths)
return new return n
} }
// Prefix gets the prefix of route `r` // Prefix gets the prefix of route `r`
...@@ -71,8 +74,8 @@ func (r *Route) Pfxlen() uint8 { ...@@ -71,8 +74,8 @@ func (r *Route) Pfxlen() uint8 {
// Paths returns a copy of the list of paths associated with route r // Paths returns a copy of the list of paths associated with route r
func (r *Route) Paths() []*Path { func (r *Route) Paths() []*Path {
if r.paths == nil { if r == nil || r.paths == nil {
return []*Path{} return nil
} }
ret := make([]*Path, len(r.paths)) ret := make([]*Path, len(r.paths))
...@@ -82,11 +85,17 @@ func (r *Route) Paths() []*Path { ...@@ -82,11 +85,17 @@ func (r *Route) Paths() []*Path {
// ECMPPathCount returns the count of ecmp paths for route r // ECMPPathCount returns the count of ecmp paths for route r
func (r *Route) ECMPPathCount() uint { func (r *Route) ECMPPathCount() uint {
if r == nil {
return 0
}
return r.ecmpPaths return r.ecmpPaths
} }
// ECMPPaths returns a copy of the list of paths associated with route r // ECMPPaths returns a copy of the list of paths associated with route r
func (r *Route) ECMPPaths() []*Path { func (r *Route) ECMPPaths() []*Path {
if r == nil {
return nil
}
r.mu.Lock() r.mu.Lock()
defer r.mu.Unlock() defer r.mu.Unlock()
...@@ -101,6 +110,9 @@ func (r *Route) ECMPPaths() []*Path { ...@@ -101,6 +110,9 @@ func (r *Route) ECMPPaths() []*Path {
// BestPath returns the current best path. nil if non exists // BestPath returns the current best path. nil if non exists
func (r *Route) BestPath() *Path { func (r *Route) BestPath() *Path {
if r == nil {
return nil
}
if len(r.paths) == 0 { if len(r.paths) == 0 {
return nil return nil
} }
......
...@@ -289,6 +289,9 @@ func TestCopy(t *testing.T) { ...@@ -289,6 +289,9 @@ func TestCopy(t *testing.T) {
}, },
}, },
}, },
{
name: "",
},
} }
for _, test := range tests { for _, test := range tests {
...@@ -297,6 +300,104 @@ func TestCopy(t *testing.T) { ...@@ -297,6 +300,104 @@ func TestCopy(t *testing.T) {
} }
} }
func TestECMPPathCount(t *testing.T) {
var r *Route
assert.Equal(t, uint(0), r.ECMPPathCount())
r = &Route{}
assert.Equal(t, uint(0), r.ECMPPathCount())
r.ecmpPaths = 12
assert.Equal(t, uint(12), r.ECMPPathCount())
}
func TestBestPath(t *testing.T) {
tests := []struct {
route *Route
expected *Path
}{
{
route: nil,
expected: nil,
},
{
route: &Route{},
expected: nil,
},
{
route: &Route{
paths: []*Path{
{
Type: StaticPathType,
StaticPath: &StaticPath{
NextHop: 32,
},
},
},
},
expected: &Path{
Type: StaticPathType,
StaticPath: &StaticPath{
NextHop: 32,
},
},
},
}
for _, tc := range tests {
assert.Equal(t, tc.expected, tc.route.BestPath())
}
}
func TestECMPPaths(t *testing.T) {
tests := []struct {
route *Route
expected []*Path
}{
{
route: nil,
expected: nil,
},
{
route: &Route{},
expected: nil,
},
{
route: &Route{
ecmpPaths: 2,
paths: []*Path{
{
Type: StaticPathType,
StaticPath: &StaticPath{
NextHop: 32,
},
},
{
Type: StaticPathType,
StaticPath: &StaticPath{
NextHop: 32,
},
},
},
},
expected: []*Path{
{
Type: StaticPathType,
StaticPath: &StaticPath{
NextHop: 32,
},
},
{
Type: StaticPathType,
StaticPath: &StaticPath{
NextHop: 32,
},
},
},
},
}
for _, tc := range tests {
assert.Equal(t, tc.expected, tc.route.ECMPPaths())
}
}
func strAddr(s string) uint32 { func strAddr(s string) uint32 {
ret, _ := net.StrToAddr(s) ret, _ := net.StrToAddr(s)
return ret return ret
......
...@@ -125,6 +125,26 @@ func (a *LocRIB) removePathsFromClients(oldRoute *route.Route, newRoute *route.R ...@@ -125,6 +125,26 @@ func (a *LocRIB) removePathsFromClients(oldRoute *route.Route, newRoute *route.R
} }
} }
// ContainsPfxPath returns true if this prefix and path combination is
// present in this LocRIB.
func (a *LocRIB) ContainsPfxPath(pfx net.Prefix, p *route.Path) bool {
a.mu.RLock()
defer a.mu.RUnlock()
r := a.rt.Get(pfx)
if r == nil {
return false
}
for _, path := range r.Paths() {
if path.Compare(p) == 0 {
return true
}
}
return false
}
func (a *LocRIB) Print() string { func (a *LocRIB) Print() string {
a.mu.RLock() a.mu.RLock()
defer a.mu.RUnlock() defer a.mu.RUnlock()
......
package locRIB
import (
"testing"
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route"
"github.com/stretchr/testify/assert"
)
type pfxPath struct {
pfx net.Prefix
path *route.Path
}
type containsPfxPathTestcase struct {
in []pfxPath
check pfxPath
expected bool
}
func TestContainsPfxPath(t *testing.T) {
testCases := []containsPfxPathTestcase{
{
in: []pfxPath{},
check: pfxPath{
pfx: net.NewPfx(1, 32),
path: nil,
},
expected: false,
},
// Not equal path
{
in: []pfxPath{
{
pfx: net.NewPfx(1, 32),
path: &route.Path{
Type: route.StaticPathType,
StaticPath: &route.StaticPath{
NextHop: 2,
},
},
},
},
check: pfxPath{
pfx: net.NewPfx(1, 32),
path: nil,
},
expected: false,
},
// Equal
{
in: []pfxPath{
{
pfx: net.NewPfx(1, 32),
path: &route.Path{
Type: route.StaticPathType,
StaticPath: &route.StaticPath{
NextHop: 2,
},
},
},
},
check: pfxPath{
pfx: net.NewPfx(1, 32),
path: &route.Path{
Type: route.StaticPathType,
StaticPath: &route.StaticPath{
NextHop: 2,
},
},
},
expected: true,
},
}
for i, tc := range testCases {
rib := New()
for _, p := range tc.in {
err := rib.AddPath(p.pfx, p.path)
assert.Nil(t, err, "could not fill rib in testcase %v", i)
}
contains := rib.ContainsPfxPath(tc.check.pfx, tc.check.path)
assert.Equal(t, tc.expected, contains, "mismatch in testcase %v", i)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment