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 @@
Cedric Kienzler
Daniel Czerwonk
Oliver Herms
Christoph Petrausch
......@@ -7,3 +7,4 @@
Cedric Kienzler
Daniel Czerwonk
Oliver Herms
Christoph Petrausch
\ No newline at end of file
......@@ -10,6 +10,16 @@ type Path struct {
// Compare returns negative if p < q, 0 if paths are equal, positive if p > q
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 {
return 1
}
......
......@@ -45,13 +45,16 @@ func NewRoute(pfx net.Prefix, p *Path) *Route {
// Copy returns a copy of route r
func (r *Route) Copy() *Route {
new := &Route{
if r == nil {
return nil
}
n := &Route{
pfx: r.pfx,
ecmpPaths: r.ecmpPaths,
}
new.paths = make([]*Path, len(r.paths))
copy(new.paths, r.paths)
return new
n.paths = make([]*Path, len(r.paths))
copy(n.paths, r.paths)
return n
}
// Prefix gets the prefix of route `r`
......@@ -71,8 +74,8 @@ func (r *Route) Pfxlen() uint8 {
// Paths returns a copy of the list of paths associated with route r
func (r *Route) Paths() []*Path {
if r.paths == nil {
return []*Path{}
if r == nil || r.paths == nil {
return nil
}
ret := make([]*Path, len(r.paths))
......@@ -82,11 +85,17 @@ func (r *Route) Paths() []*Path {
// ECMPPathCount returns the count of ecmp paths for route r
func (r *Route) ECMPPathCount() uint {
if r == nil {
return 0
}
return r.ecmpPaths
}
// ECMPPaths returns a copy of the list of paths associated with route r
func (r *Route) ECMPPaths() []*Path {
if r == nil {
return nil
}
r.mu.Lock()
defer r.mu.Unlock()
......@@ -101,6 +110,9 @@ func (r *Route) ECMPPaths() []*Path {
// BestPath returns the current best path. nil if non exists
func (r *Route) BestPath() *Path {
if r == nil {
return nil
}
if len(r.paths) == 0 {
return nil
}
......
......@@ -289,6 +289,9 @@ func TestCopy(t *testing.T) {
},
},
},
{
name: "",
},
}
for _, test := range tests {
......@@ -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 {
ret, _ := net.StrToAddr(s)
return ret
......
......@@ -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 {
a.mu.RLock()
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.
Finish editing this message first!
Please register or to comment