Skip to content
Snippets Groups Projects
Commit 6874b03b authored by cedi's avatar cedi
Browse files

Add unit-tests

parent 7b324ae3
No related branches found
No related tags found
No related merge requests found
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "go_default_library",
srcs = [
"main.go",
"main_ipv4.go",
],
importpath = "github.com/bio-routing/bio-rd/examples/netlink",
visibility = ["//visibility:private"],
deps = [
"//config:go_default_library",
"//net:go_default_library",
"//protocols/bgp/server:go_default_library",
"//protocols/netlink:go_default_library",
"//routingtable:go_default_library",
"//routingtable/filter:go_default_library",
"//routingtable/locRIB:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
],
)
go_binary(
name = "netlink",
embed = [":go_default_library"],
visibility = ["//visibility:public"],
)
package main
import (
"net"
"os"
"time"
"github.com/bio-routing/bio-rd/config"
"github.com/bio-routing/bio-rd/protocols/bgp/server"
"github.com/bio-routing/bio-rd/protocols/netlink"
"github.com/bio-routing/bio-rd/routingtable/locRIB"
log "github.com/sirupsen/logrus"
bnet "github.com/bio-routing/bio-rd/net"
)
func strAddr(s string) uint32 {
ret, _ := bnet.StrToAddr(s)
return ret
}
func main() {
log.SetLevel(log.DebugLevel)
f, err := os.OpenFile("/var/log/bio-rd.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
defer f.Close()
log.SetOutput(f)
log.Info("bio-routing started...\n")
cfg := &config.Global{
Listen: true,
LocalAddressList: []net.IP{
net.IPv4(169, 254, 0, 2),
},
}
rib := locRIB.New()
b := server.NewBgpServer()
startBGPServer(b, rib, cfg)
// Netlink communication
n := protocolnetlink.NewNetlink(&config.Netlink{
HoldTime: time.Second * 15,
UpdateInterval: time.Second * 15,
RoutingTable: config.RtMain,
}, rib)
n.Start()
go func() {
for {
log.Debugf("LocRIB count: %d", rib.Count())
log.Debugf(rib.String())
time.Sleep(time.Second * 10)
}
}()
select {}
}
package main
import (
"time"
"github.com/bio-routing/bio-rd/routingtable"
"github.com/bio-routing/bio-rd/routingtable/locRIB"
"github.com/bio-routing/bio-rd/config"
"github.com/bio-routing/bio-rd/protocols/bgp/server"
"github.com/bio-routing/bio-rd/routingtable/filter"
log "github.com/sirupsen/logrus"
bnet "github.com/bio-routing/bio-rd/net"
)
func startBGPServer(b server.BGPServer, rib *locRIB.LocRIB, cfg *config.Global) {
err := b.Start(cfg)
if err != nil {
log.Fatalf("Unable to start BGP server: %v", err)
}
b.AddPeer(config.Peer{
AdminEnabled: true,
LocalAS: 65200,
PeerAS: 65100,
PeerAddress: bnet.IPv4FromOctets(169, 254, 0, 1),
LocalAddress: bnet.IPv4FromOctets(169, 254, 0, 2),
ReconnectInterval: time.Second * 20,
HoldTime: time.Second * 20,
KeepAlive: time.Second * 20,
Passive: false,
RouterID: b.RouterID(),
//AddPathSend: routingtable.ClientOptions{
// MaxPaths: 10,
//},
//RouteServerClient: true,
IPv4: &config.AddressFamilyConfig{
RIB: rib,
ImportFilter: filter.NewAcceptAllFilter(),
ExportFilter: filter.NewAcceptAllFilter(),
AddPathSend: routingtable.ClientOptions{
MaxPaths: 10,
},
AddPathRecv: true,
},
})
}
// +build ipv6
package main
import (
"net"
"time"
"github.com/bio-routing/bio-rd/config"
"github.com/bio-routing/bio-rd/protocols/bgp/server"
"github.com/bio-routing/bio-rd/routingtable"
"github.com/bio-routing/bio-rd/routingtable/filter"
"github.com/bio-routing/bio-rd/routingtable/locRIB"
"github.com/sirupsen/logrus"
bnet "github.com/bio-routing/bio-rd/net"
)
func startServer(b server.BGPServer, rib *locRIB.LocRIB) {
err := b.Start(&config.Global{
Listen: true,
LocalAddressList: []net.IP{
net.IP{0x20, 0x01, 0x6, 0x78, 0x1, 0xe0, 0, 0, 0, 0, 0, 0, 0, 0, 0xca, 0xfe},
},
})
if err != nil {
logrus.Fatalf("Unable to start BGP server: %v", err)
}
b.AddPeer(config.Peer{
AdminEnabled: true,
LocalAS: 65200,
PeerAS: 202739,
PeerAddress: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 1),
LocalAddress: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0xcafe),
ReconnectInterval: time.Second * 15,
HoldTime: time.Second * 90,
KeepAlive: time.Second * 30,
Passive: true,
RouterID: b.RouterID(),
IPv6: &config.AddressFamilyConfig{
RIB: rib,
ImportFilter: filter.NewAcceptAllFilter(),
ExportFilter: filter.NewDrainFilter(),
AddPathSend: routingtable.ClientOptions{
BestOnly: true,
},
},
})
b.AddPeer(config.Peer{
AdminEnabled: true,
LocalAS: 65200,
PeerAS: 65400,
PeerAddress: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0xcafe, 0, 0, 0, 5),
LocalAddress: bnet.IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0xcafe),
ReconnectInterval: time.Second * 15,
HoldTime: time.Second * 90,
KeepAlive: time.Second * 30,
Passive: true,
RouterID: b.RouterID(),
IPv6: &config.AddressFamilyConfig{
RIB: rib,
ImportFilter: filter.NewDrainFilter(),
ExportFilter: filter.NewAcceptAllFilter(),
AddPathSend: routingtable.ClientOptions{
BestOnly: true,
},
},
})
}
......@@ -15,7 +15,6 @@ go_library(
deps = [
"//net:go_default_library",
"//protocols/bgp/types:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
"//vendor/github.com/taktv6/tflow2/convert:go_default_library",
"//vendor/github.com/vishvananda/netlink:go_default_library",
],
......
......@@ -52,18 +52,18 @@ func NewPathsFromNlRoute(r netlink.Route, kernel bool) (bnet.Prefix, []*Path, er
if r.Src == nil && r.Dst != nil {
dst = bnet.NewPfxFromIPNet(r.Dst)
if dst.Addr().IsIPv4() {
src = bnet.IPv4FromOctets(0, 0, 0, 0)
src = bnet.IPv4(0)
} else {
src = bnet.IPv6FromBlocks(0, 0, 0, 0, 0, 0, 0, 0)
src = bnet.IPv6(0, 0)
}
}
if r.Src != nil && r.Dst == nil {
src, _ = bnet.IPFromBytes(r.Src)
if src.IsIPv4() {
dst = bnet.NewPfx(bnet.IPv4FromOctets(0, 0, 0, 0), 0)
dst = bnet.NewPfx(bnet.IPv4(0), 0)
} else {
dst = bnet.NewPfx(bnet.IPv6FromBlocks(0, 0, 0, 0, 0, 0, 0, 0), 0)
dst = bnet.NewPfx(bnet.IPv6(0, 0), 0)
}
}
......@@ -111,19 +111,19 @@ func NewPathsFromNlRoute(r netlink.Route, kernel bool) (bnet.Prefix, []*Path, er
// Select compares s with t and returns negative if s < t, 0 if paths are equal, positive if s > t
func (s *NetlinkPath) Select(t *NetlinkPath) int8 {
if s.NextHop.Compare(t.NextHop) > 0 {
if s.NextHop.Compare(t.NextHop) < 0 {
return -1
}
if s.NextHop.Compare(t.NextHop) < 0 {
if s.NextHop.Compare(t.NextHop) > 0 {
return 1
}
if s.Src.Compare(t.Src) > 0 {
if s.Src.Compare(t.Src) < 0 {
return -1
}
if s.Src.Compare(t.Src) < 0 {
if s.Src.Compare(t.Src) > 0 {
return 1
}
......@@ -156,28 +156,7 @@ func (s *NetlinkPath) Select(t *NetlinkPath) int8 {
// ECMP determines if path s and t are equal in terms of ECMP
func (s *NetlinkPath) ECMP(t *NetlinkPath) bool {
if s.Src != t.Src {
return false
}
if s.Priority != t.Priority {
return false
}
if s.Protocol != t.Protocol {
return false
}
if s.Type != t.Type {
return false
}
if s.Table != t.Table {
return false
}
return true
return s.Src == t.Src && s.Priority == t.Priority && s.Protocol == t.Protocol && s.Type == t.Type && s.Table == t.Table
}
// Copy duplicates the current object
......
......@@ -451,90 +451,140 @@ func TestNewPathsFromNetlinkRoute(t *testing.T) {
},
expectError: false,
},
// {
// name: "No source but destination",
// source: &netlink.Route{
// Dst: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).GetIPNet(),
// Gw: bnet.IPv4(789).Bytes(),
// Protocol: ProtoKernel,
// Priority: 1,
// Table: 254,
// Type: 1,
// },
// expected: &NetlinkPath{
// Src: bnet.IPv4FromOctets(0, 0, 0, 0),
// NextHop: bnet.IPv4(789),
// Protocol: ProtoKernel,
// Priority: 1,
// Table: 254,
// Type: 1,
// Kernel: true,
// },
// expectError: false,
// },
// {
// name: "Source but no destination",
// source: &netlink.Route{
// Src: bnet.IPv4(456).Bytes(),
// Gw: bnet.IPv4(789).Bytes(),
// Protocol: ProtoKernel,
// Priority: 1,
// Table: 254,
// Type: 1,
// },
// expected: &NetlinkPath{
// Src: bnet.IPv4(456),
// NextHop: bnet.IPv4(789),
// Protocol: ProtoKernel,
// Priority: 1,
// Table: 254,
// Type: 1,
// Kernel: true,
// },
// expectError: false,
// },
// {
// name: "No source but destination IPv6",
// source: &netlink.Route{
// Dst: bnet.NewPfx(bnet.IPv6(2001, 0), 48).GetIPNet(),
// Gw: bnet.IPv6(2001, 2).Bytes(),
// Protocol: ProtoKernel,
// Priority: 1,
// Table: 254,
// Type: 1,
// },
// expected: &NetlinkPath{
// Src: bnet.IPv6FromBlocks(0, 0, 0, 0, 0, 0, 0, 0),
// NextHop: bnet.IPv6(2001, 2),
// Protocol: ProtoKernel,
// Priority: 1,
// Table: 254,
// Type: 1,
// Kernel: true,
// },
// expectError: false,
// },
// {
// name: "Source but no destination IPv6",
// source: &netlink.Route{
// Src: bnet.IPv6(2001, 0).Bytes(),
// Gw: bnet.IPv6(2001, 2).Bytes(),
// Protocol: ProtoKernel,
// Priority: 1,
// Table: 254,
// Type: 1,
// },
// expected: &NetlinkPath{
// Src: bnet.IPv6(2001, 0),
// NextHop: bnet.IPv6(2001, 2),
// Protocol: ProtoKernel,
// Priority: 1,
// Table: 254,
// Type: 1,
// Kernel: true,
// },
// expectError: false,
// },
{
name: "No source but destination",
source: netlink.Route{
Dst: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).GetIPNet(),
Gw: bnet.IPv4(789).Bytes(),
Protocol: ProtoKernel,
Priority: 1,
Table: 254,
Type: 1,
},
expectedPfx: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8),
expectedPaths: []*Path{
{
Type: NetlinkPathType,
NetlinkPath: &NetlinkPath{
Src: bnet.IPv4(0),
NextHop: bnet.IPv4(789),
Protocol: ProtoKernel,
Priority: 1,
Table: 254,
Type: 1,
Kernel: true,
},
},
},
expectError: false,
},
{
name: "Source but no destination",
source: netlink.Route{
Src: bnet.IPv4(456).Bytes(),
Gw: bnet.IPv4(789).Bytes(),
Protocol: ProtoKernel,
Priority: 1,
Table: 254,
Type: 1,
},
expectedPfx: bnet.NewPfx(bnet.IPv4FromOctets(0, 0, 0, 0), 0),
expectedPaths: []*Path{
{
Type: NetlinkPathType,
NetlinkPath: &NetlinkPath{
Src: bnet.IPv4(456),
NextHop: bnet.IPv4(789),
Protocol: ProtoKernel,
Priority: 1,
Table: 254,
Type: 1,
Kernel: true,
},
},
},
expectError: false,
},
{
name: "No source but no destination",
source: netlink.Route{
Gw: bnet.IPv4(789).Bytes(),
Protocol: ProtoKernel,
Priority: 1,
Table: 254,
Type: 1,
},
expectedPfx: bnet.Prefix{},
expectedPaths: []*Path{},
expectError: true,
},
{
name: "No source but destination IPv6",
source: netlink.Route{
Dst: bnet.NewPfx(bnet.IPv6(2001, 0), 48).GetIPNet(),
Gw: bnet.IPv6(2001, 123).Bytes(),
Protocol: ProtoKernel,
Priority: 1,
Table: 254,
Type: 1,
},
expectedPfx: bnet.NewPfx(bnet.IPv6(2001, 0), 48),
expectedPaths: []*Path{
{
Type: NetlinkPathType,
NetlinkPath: &NetlinkPath{
Src: bnet.IPv6(0, 0),
NextHop: bnet.IPv6(2001, 123),
Protocol: ProtoKernel,
Priority: 1,
Table: 254,
Type: 1,
Kernel: true,
},
},
},
expectError: false,
},
{
name: "Source but no destination IPv6",
source: netlink.Route{
Src: bnet.IPv6(2001, 456).Bytes(),
Gw: bnet.IPv6(2001, 789).Bytes(),
Protocol: ProtoKernel,
Priority: 1,
Table: 254,
Type: 1,
},
expectedPfx: bnet.NewPfx(bnet.IPv6(0, 0), 0),
expectedPaths: []*Path{
{
Type: NetlinkPathType,
NetlinkPath: &NetlinkPath{
Src: bnet.IPv6(2001, 456),
NextHop: bnet.IPv6(2001, 789),
Protocol: ProtoKernel,
Priority: 1,
Table: 254,
Type: 1,
Kernel: true,
},
},
},
expectError: false,
},
{
name: "no source no destination",
source: netlink.Route{
Gw: bnet.IPv4(123).Bytes(),
Protocol: ProtoKernel,
Priority: 1,
Table: 254,
Type: 1,
},
expectedPfx: bnet.NewPfx(bnet.IPv4(0), 0),
expectedPaths: []*Path{{}},
expectError: true,
},
}
for _, test := range tests {
......@@ -548,3 +598,272 @@ func TestNewPathsFromNetlinkRoute(t *testing.T) {
}
}
}
func TestECMP(t *testing.T) {
tests := []struct {
name string
left *Path
right *Path
ecmp bool
}{
{
name: "BGP Path ecmp",
left: &Path{
Type: BGPPathType,
BGPPath: &BGPPath{
LocalPref: 100,
ASPathLen: 10,
MED: 1,
Origin: 123,
},
},
right: &Path{
Type: BGPPathType,
BGPPath: &BGPPath{
LocalPref: 100,
ASPathLen: 10,
MED: 1,
Origin: 123,
},
},
ecmp: true,
}, {
name: "BGP Path not ecmp",
left: &Path{
Type: BGPPathType,
BGPPath: &BGPPath{
LocalPref: 100,
ASPathLen: 10,
MED: 1,
Origin: 123,
},
},
right: &Path{
Type: BGPPathType,
BGPPath: &BGPPath{
LocalPref: 100,
ASPathLen: 5,
MED: 1,
Origin: 123,
},
},
ecmp: false,
}, {
name: "Netlink Path ecmp",
left: &Path{
Type: NetlinkPathType,
NetlinkPath: &NetlinkPath{
Src: bnet.IPv4(123),
Priority: 1,
Protocol: 1,
Type: 1,
Table: 1,
},
},
right: &Path{
Type: NetlinkPathType,
NetlinkPath: &NetlinkPath{
Src: bnet.IPv4(123),
Priority: 1,
Protocol: 1,
Type: 1,
Table: 1,
},
},
ecmp: true,
}, {
name: "Netlink Path not ecmp",
left: &Path{
Type: NetlinkPathType,
NetlinkPath: &NetlinkPath{
Src: bnet.IPv4(123),
Priority: 1,
Protocol: 1,
Type: 1,
Table: 1,
},
},
right: &Path{
Type: NetlinkPathType,
NetlinkPath: &NetlinkPath{
Src: bnet.IPv4(123),
Priority: 2,
Protocol: 1,
Type: 1,
Table: 1,
},
},
ecmp: false,
}, {
name: "static Path ecmp",
left: &Path{
Type: StaticPathType,
StaticPath: &StaticPath{
NextHop: bnet.IPv4(123),
},
},
right: &Path{
Type: StaticPathType,
StaticPath: &StaticPath{
NextHop: bnet.IPv4(123),
},
},
ecmp: true,
}, {
name: "static Path not ecmp",
left: &Path{
Type: StaticPathType,
StaticPath: &StaticPath{
NextHop: bnet.IPv4(123),
},
},
right: &Path{
Type: StaticPathType,
StaticPath: &StaticPath{
NextHop: bnet.IPv4(345),
},
},
// ECMP is always true for staticPath
ecmp: true,
},
}
for _, test := range tests {
ecmp := test.left.ECMP(test.right)
assert.Equal(t, test.ecmp, ecmp, test.name)
}
}
func TestNetlinkPathSelect(t *testing.T) {
tests := []struct {
name string
left *NetlinkPath
right *NetlinkPath
expected int8
}{
{
name: "equal",
left: &NetlinkPath{
NextHop: bnet.IPv4(123),
Src: bnet.IPv4(234),
Priority: 1,
Protocol: 1,
Table: 1,
},
right: &NetlinkPath{
NextHop: bnet.IPv4(123),
Src: bnet.IPv4(234),
Priority: 1,
Protocol: 1,
Table: 1,
},
expected: 0,
},
{
name: "nextHop smaller",
left: &NetlinkPath{
NextHop: bnet.IPv4(1),
},
right: &NetlinkPath{
NextHop: bnet.IPv4(2),
},
expected: -1,
},
{
name: "nextHop bigger",
left: &NetlinkPath{
NextHop: bnet.IPv4(2),
},
right: &NetlinkPath{
NextHop: bnet.IPv4(1),
},
expected: 1,
},
{
name: "src smaller",
left: &NetlinkPath{
Src: bnet.IPv4(1),
},
right: &NetlinkPath{
Src: bnet.IPv4(2),
},
expected: -1,
},
{
name: "src bigger",
left: &NetlinkPath{
Src: bnet.IPv4(2),
},
right: &NetlinkPath{
Src: bnet.IPv4(1),
},
expected: 1,
},
{
name: "priority smaller",
left: &NetlinkPath{
Priority: 1,
},
right: &NetlinkPath{
Priority: 2,
},
expected: -1,
},
{
name: "priority bigger",
left: &NetlinkPath{
Priority: 2,
},
right: &NetlinkPath{
Priority: 1,
},
expected: 1,
},
{
name: "protocol smaller",
left: &NetlinkPath{
Protocol: 1,
},
right: &NetlinkPath{
Protocol: 2,
},
expected: -1,
},
{
name: "protocol bigger",
left: &NetlinkPath{
Protocol: 2,
},
right: &NetlinkPath{
Protocol: 1,
},
expected: 1,
},
{
name: "table smaller",
left: &NetlinkPath{
Table: 1,
},
right: &NetlinkPath{
Table: 2,
},
expected: -1,
},
{
name: "table bigger",
left: &NetlinkPath{
Table: 2,
},
right: &NetlinkPath{
Table: 1,
},
expected: 1,
},
}
for _, test := range tests {
result := test.left.Select(test.right)
assert.Equal(t, test.expected, result, test.name)
}
}
......@@ -175,6 +175,23 @@ func (a *LocRIB) ContainsPfxPath(pfx net.Prefix, p *route.Path) bool {
return false
}
func (a *LocRIB) String() string {
a.mu.RLock()
defer a.mu.RUnlock()
ret := ""
routes := a.rt.Dump()
for idx, r := range routes {
if idx < len(routes)-1 {
ret += fmt.Sprintf("%s, ", r.Prefix().String())
} else {
ret += fmt.Sprintf("%s", r.Prefix().String())
}
}
return ret
}
func (a *LocRIB) Print() string {
a.mu.RLock()
defer a.mu.RUnlock()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment