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

Merge pull request #52 from bio-routing/feature/rs

Implemented Route Server support
parents d873c951 b54ca9e1
Branches
Tags
No related merge requests found
Showing
with 233 additions and 396 deletions
......@@ -23,4 +23,5 @@ type Peer struct {
AddPathRecv bool
ImportFilter *filter.Filter
ExportFilter *filter.Filter
RouteServerClient bool
}
......@@ -40,7 +40,7 @@ func main() {
b.AddPeer(config.Peer{
AdminEnabled: true,
LocalAS: 65200,
LocalAS: 6695,
PeerAS: 65300,
PeerAddress: net.IP([]byte{169, 254, 200, 1}),
LocalAddress: net.IP([]byte{169, 254, 200, 0}),
......@@ -52,13 +52,14 @@ func main() {
AddPathSend: routingtable.ClientOptions{
MaxPaths: 10,
},
ImportFilter: filter.NewDrainFilter(),
ExportFilter: filter.NewAcceptAllFilter(),
ImportFilter: filter.NewAcceptAllFilter(),
ExportFilter: filter.NewAcceptAllFilter(),
RouteServerClient: true,
}, rib)
b.AddPeer(config.Peer{
AdminEnabled: true,
LocalAS: 65200,
LocalAS: 6695,
PeerAS: 65100,
PeerAddress: net.IP([]byte{169, 254, 100, 0}),
LocalAddress: net.IP([]byte{169, 254, 100, 1}),
......@@ -70,9 +71,10 @@ func main() {
AddPathSend: routingtable.ClientOptions{
MaxPaths: 10,
},
AddPathRecv: true,
ImportFilter: filter.NewAcceptAllFilter(),
ExportFilter: filter.NewDrainFilter(),
AddPathRecv: true,
ImportFilter: filter.NewAcceptAllFilter(),
ExportFilter: filter.NewAcceptAllFilter(),
RouteServerClient: true,
}, rib)
go func() {
......
......@@ -3,7 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"fsm2.go",
"fsm.go",
"fsm_active.go",
"fsm_cease.go",
"fsm_connect.go",
......@@ -32,7 +32,6 @@ go_library(
"//routingtable:go_default_library",
"//routingtable/adjRIBIn:go_default_library",
"//routingtable/adjRIBOut:go_default_library",
"//routingtable/adjRIBOutAddPath:go_default_library",
"//routingtable/filter:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
],
......@@ -47,9 +46,12 @@ go_test(
],
embed = [":go_default_library"],
deps = [
"//config:go_default_library",
"//net:go_default_library",
"//protocols/bgp/packet:go_default_library",
"//route:go_default_library",
"//routingtable:go_default_library",
"//routingtable/filter:go_default_library",
"//routingtable/locRIB:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
],
......
File moved
......@@ -3,14 +3,14 @@ package server
import (
"bytes"
"fmt"
"net"
tnet "github.com/bio-routing/bio-rd/net"
bnet "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/protocols/bgp/packet"
"github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable"
"github.com/bio-routing/bio-rd/routingtable/adjRIBIn"
"github.com/bio-routing/bio-rd/routingtable/adjRIBOut"
"github.com/bio-routing/bio-rd/routingtable/adjRIBOutAddPath"
)
type establishedState struct {
......@@ -25,7 +25,10 @@ func newEstablishedState(fsm *FSM) *establishedState {
func (s establishedState) run() (state, string) {
if !s.fsm.ribsInitialized {
s.init()
err := s.init()
if err != nil {
return newCeaseState(), fmt.Sprintf("Init failed: %v", err)
}
}
for {
......@@ -51,45 +54,51 @@ func (s establishedState) run() (state, string) {
}
}
func (s *establishedState) init() {
s.fsm.adjRIBIn = adjRIBIn.New()
func (s *establishedState) init() error {
s.fsm.adjRIBIn = adjRIBIn.New(s.fsm.peer.importFilter)
s.fsm.adjRIBIn.Register(s.fsm.rib)
s.fsm.peer.importFilter.Register(s.fsm.rib)
s.fsm.adjRIBIn.Register(s.fsm.peer.importFilter)
host, _, err := net.SplitHostPort(s.fsm.con.LocalAddr().String())
if err != nil {
return fmt.Errorf("Unable to get local address: %v", err)
}
hostIP := net.ParseIP(host)
if hostIP == nil {
return fmt.Errorf("Unable to parse address: %v", err)
}
n := &routingtable.Neighbor{
Type: route.BGPPathType,
Address: tnet.IPv4ToUint32(s.fsm.peer.addr),
IBGP: s.fsm.peer.localASN == s.fsm.peer.peerASN,
LocalASN: s.fsm.peer.localASN,
Type: route.BGPPathType,
Address: bnet.IPv4ToUint32(s.fsm.peer.addr),
IBGP: s.fsm.peer.localASN == s.fsm.peer.peerASN,
LocalASN: s.fsm.peer.localASN,
RouteServerClient: s.fsm.peer.routeServerClient,
LocalAddress: bnet.IPv4ToUint32(hostIP),
CapAddPathRX: s.fsm.capAddPathSend,
}
s.fsm.adjRIBOut = adjRIBOut.New(n, s.fsm.peer.exportFilter)
clientOptions := routingtable.ClientOptions{
BestOnly: true,
}
if s.fsm.capAddPathSend {
s.fsm.updateSender = newUpdateSenderAddPath(s.fsm)
s.fsm.adjRIBOut = adjRIBOutAddPath.New(n)
clientOptions = s.fsm.peer.addPathSend
} else {
s.fsm.updateSender = newUpdateSender(s.fsm)
s.fsm.adjRIBOut = adjRIBOut.New(n)
}
s.fsm.adjRIBOut.Register(s.fsm.updateSender)
s.fsm.peer.exportFilter.Register(s.fsm.adjRIBOut)
s.fsm.rib.RegisterWithOptions(s.fsm.peer.exportFilter, clientOptions)
s.fsm.rib.RegisterWithOptions(s.fsm.adjRIBOut, clientOptions)
s.fsm.ribsInitialized = true
return nil
}
func (s *establishedState) uninit() {
s.fsm.adjRIBIn.Unregister(s.fsm.peer.importFilter)
s.fsm.peer.importFilter.Unregister(s.fsm.rib)
s.fsm.rib.Unregister(s.fsm.peer.exportFilter)
s.fsm.peer.exportFilter.Unregister(s.fsm.adjRIBOut)
s.fsm.updateSender.Unregister(s.fsm.adjRIBOut)
s.fsm.adjRIBIn.Unregister(s.fsm.rib)
s.fsm.rib.Unregister(s.fsm.adjRIBOut)
s.fsm.adjRIBOut.Unregister(s.fsm.updateSender)
s.fsm.adjRIBIn = nil
s.fsm.adjRIBOut = nil
......@@ -190,19 +199,19 @@ func (s *establishedState) update(msg *packet.BGPMessage) (state, string) {
func (s *establishedState) withdraws(u *packet.BGPUpdate) {
for r := u.WithdrawnRoutes; r != nil; r = r.Next {
pfx := tnet.NewPfx(r.IP, r.Pfxlen)
pfx := bnet.NewPfx(r.IP, r.Pfxlen)
s.fsm.adjRIBIn.RemovePath(pfx, nil)
}
}
func (s *establishedState) updates(u *packet.BGPUpdate) {
for r := u.NLRI; r != nil; r = r.Next {
pfx := tnet.NewPfx(r.IP, r.Pfxlen)
pfx := bnet.NewPfx(r.IP, r.Pfxlen)
path := &route.Path{
Type: route.BGPPathType,
BGPPath: &route.BGPPath{
Source: tnet.IPv4ToUint32(s.fsm.peer.addr),
Source: bnet.IPv4ToUint32(s.fsm.peer.addr),
},
}
......
......@@ -37,6 +37,7 @@ type peer struct {
optOpenParams []packet.OptParam
importFilter *filter.Filter
exportFilter *filter.Filter
routeServerClient bool
}
func (p *peer) snapshot() PeerInfo {
......@@ -118,6 +119,7 @@ func newPeer(c config.Peer, rib routingtable.RouteTableClient, server *bgpServer
optOpenParams: make([]packet.OptParam, 0),
importFilter: filterOrDefault(c.ImportFilter),
exportFilter: filterOrDefault(c.ExportFilter),
routeServerClient: c.RouteServerClient,
}
p.fsms = append(p.fsms, NewActiveFSM2(p))
......
......@@ -82,6 +82,7 @@ func serializeAndSendUpdate(out io.Writer, update serializeAbleUpdate) error {
return nil
}
fmt.Printf("Sending Update: %v\n", updateBytes)
_, err = out.Write(updateBytes)
if err != nil {
return fmt.Errorf("Failed sending Update: %v", err)
......
......@@ -158,6 +158,10 @@ func (b *BGPPath) Print() string {
nh := uint32To4Byte(b.NextHop)
ret += fmt.Sprintf("\t\tNEXT HOP: %d.%d.%d.%d\n", nh[0], nh[1], nh[2], nh[3])
ret += fmt.Sprintf("\t\tMED: %d\n", b.MED)
ret += fmt.Sprintf("\t\tPath ID: %d\n", b.PathIdentifier)
ret += fmt.Sprintf("\t\tSource: %d\n", b.Source)
ret += fmt.Sprintf("\t\tCommunities: %s\n", b.Communities)
ret += fmt.Sprintf("\t\tLargeCommunities: %s\n", b.LargeCommunities)
return ret
}
......
......@@ -9,6 +9,7 @@ go_library(
"//net:go_default_library",
"//route:go_default_library",
"//routingtable:go_default_library",
"//routingtable/filter:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
],
)
......@@ -21,6 +22,7 @@ go_test(
"//net:go_default_library",
"//route:go_default_library",
"//routingtable:go_default_library",
"//routingtable/filter:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
],
)
......@@ -3,6 +3,8 @@ package adjRIBIn
import (
"sync"
"github.com/bio-routing/bio-rd/routingtable/filter"
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable"
......@@ -12,14 +14,16 @@ import (
// AdjRIBIn represents an Adjacency RIB In as described in RFC4271
type AdjRIBIn struct {
routingtable.ClientManager
rt *routingtable.RoutingTable
mu sync.RWMutex
rt *routingtable.RoutingTable
mu sync.RWMutex
exportFilter *filter.Filter
}
// New creates a new Adjacency RIB In
func New() *AdjRIBIn {
func New(exportFilter *filter.Filter) *AdjRIBIn {
a := &AdjRIBIn{
rt: routingtable.NewRoutingTable(),
rt: routingtable.NewRoutingTable(),
exportFilter: exportFilter,
}
a.ClientManager = routingtable.NewClientManager(a)
return a
......@@ -34,6 +38,10 @@ func (a *AdjRIBIn) UpdateNewClient(client routingtable.RouteTableClient) error {
for _, route := range routes {
paths := route.Paths()
for _, path := range paths {
path, reject := a.exportFilter.ProcessTerms(route.Prefix(), path)
if reject {
continue
}
err := client.AddPath(route.Prefix(), path)
if err != nil {
......@@ -52,6 +60,11 @@ func (a *AdjRIBIn) AddPath(pfx net.Prefix, p *route.Path) error {
oldPaths := a.rt.ReplacePath(pfx, p)
a.removePathsFromClients(pfx, oldPaths)
p, reject := a.exportFilter.ProcessTerms(pfx, p)
if reject {
return nil
}
for _, client := range a.ClientManager.Clients() {
client.AddPath(pfx, p)
}
......@@ -79,6 +92,10 @@ func (a *AdjRIBIn) RemovePath(pfx net.Prefix, p *route.Path) bool {
func (a *AdjRIBIn) removePathsFromClients(pfx net.Prefix, paths []*route.Path) {
for _, path := range paths {
path, reject := a.exportFilter.ProcessTerms(pfx, path)
if reject {
continue
}
for _, client := range a.ClientManager.Clients() {
client.RemovePath(pfx, path)
}
......
......@@ -4,6 +4,8 @@ import (
"fmt"
"testing"
"github.com/bio-routing/bio-rd/routingtable/filter"
"github.com/stretchr/testify/assert"
"github.com/bio-routing/bio-rd/net"
......@@ -113,7 +115,7 @@ func TestAddPath(t *testing.T) {
}
for _, test := range tests {
adjRIBIn := New()
adjRIBIn := New(filter.NewAcceptAllFilter())
mc := NewRTMockClient()
adjRIBIn.ClientManager.Register(mc)
......@@ -204,7 +206,7 @@ func TestRemovePath(t *testing.T) {
}
for _, test := range tests {
adjRIBIn := New()
adjRIBIn := New(filter.NewAcceptAllFilter())
for _, route := range test.routes {
adjRIBIn.AddPath(route.Prefix(), route.Paths()[0])
}
......
......@@ -2,13 +2,17 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["adj_rib_out.go"],
srcs = [
"adj_rib_out.go",
"path_id_manager.go",
],
importpath = "github.com/bio-routing/bio-rd/routingtable/adjRIBOut",
visibility = ["//visibility:public"],
deps = [
"//net:go_default_library",
"//route:go_default_library",
"//routingtable:go_default_library",
"//routingtable/filter:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
],
)
......@@ -4,25 +4,31 @@ import (
"fmt"
"sync"
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable"
"github.com/bio-routing/bio-rd/routingtable/filter"
bnet "github.com/bio-routing/bio-rd/net"
log "github.com/sirupsen/logrus"
)
// AdjRIBOut represents an Adjacency RIB In as described in RFC4271
// AdjRIBOut represents an Adjacency RIB Out with BGP add path
type AdjRIBOut struct {
routingtable.ClientManager
rt *routingtable.RoutingTable
neighbor *routingtable.Neighbor
mu sync.RWMutex
rt *routingtable.RoutingTable
neighbor *routingtable.Neighbor
pathIDManager *pathIDManager
mu sync.RWMutex
exportFilter *filter.Filter
}
// New creates a new Adjacency RIB In
func New(neighbor *routingtable.Neighbor) *AdjRIBOut {
// New creates a new Adjacency RIB Out with BGP add path
func New(neighbor *routingtable.Neighbor, exportFilter *filter.Filter) *AdjRIBOut {
a := &AdjRIBOut{
rt: routingtable.NewRoutingTable(),
neighbor: neighbor,
rt: routingtable.NewRoutingTable(),
neighbor: neighbor,
pathIDManager: newPathIDManager(),
exportFilter: exportFilter,
}
a.ClientManager = routingtable.NewClientManager(a)
return a
......@@ -33,38 +39,64 @@ func (a *AdjRIBOut) UpdateNewClient(client routingtable.RouteTableClient) error
return nil
}
// AddPath replaces the path for prefix `pfx`. If the prefix doesn't exist it is added.
func (a *AdjRIBOut) AddPath(pfx net.Prefix, p *route.Path) error {
// AddPath adds path p to prefix `pfx`
func (a *AdjRIBOut) AddPath(pfx bnet.Prefix, p *route.Path) error {
if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
return nil
}
p = p.Copy()
if !a.neighbor.IBGP {
if !a.neighbor.IBGP && !a.neighbor.RouteServerClient {
p.BGPPath.ASPath = fmt.Sprintf("%d %s", a.neighbor.LocalASN, p.BGPPath.ASPath)
}
if !a.neighbor.IBGP && !a.neighbor.RouteServerClient {
p.BGPPath.NextHop = a.neighbor.LocalAddress
}
p, reject := a.exportFilter.ProcessTerms(pfx, p)
if reject {
return nil
}
a.mu.Lock()
defer a.mu.Unlock()
oldPaths := a.rt.ReplacePath(pfx, p)
a.removePathsFromClients(pfx, oldPaths)
if !a.neighbor.CapAddPathRX {
oldPaths := a.rt.ReplacePath(pfx, p)
a.removePathsFromClients(pfx, oldPaths)
}
fmt.Printf("Adding path: %s\n", p.Print())
pathID, err := a.pathIDManager.addPath(p)
if err != nil {
return fmt.Errorf("Unable to get path ID: %v", err)
}
fmt.Printf("New path ID: %d\n", pathID)
p.BGPPath.PathIdentifier = pathID
a.rt.AddPath(pfx, p)
for _, client := range a.ClientManager.Clients() {
err := client.AddPath(pfx, p)
if err != nil {
log.WithField("Sender", "AdjRIBOut").WithError(err).Error("Could not send update to client")
log.WithField("Sender", "AdjRIBOutAddPath").WithError(err).Error("Could not send update to client")
}
}
return nil
}
// RemovePath removes the path for prefix `pfx`
func (a *AdjRIBOut) RemovePath(pfx net.Prefix, p *route.Path) bool {
func (a *AdjRIBOut) RemovePath(pfx bnet.Prefix, p *route.Path) bool {
if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
return false
}
p, reject := a.exportFilter.ProcessTerms(pfx, p)
if reject {
return false
}
a.mu.Lock()
defer a.mu.Unlock()
......@@ -73,20 +105,41 @@ func (a *AdjRIBOut) RemovePath(pfx net.Prefix, p *route.Path) bool {
return false
}
oldPaths := r.Paths()
for _, path := range oldPaths {
a.rt.RemovePath(pfx, path)
a.rt.RemovePath(pfx, p)
pathID, err := a.pathIDManager.releasePath(p)
if err != nil {
log.Warningf("Unable to release path: %v", err)
return true
}
a.removePathsFromClients(pfx, oldPaths)
p = p.Copy()
p.BGPPath.PathIdentifier = pathID
a.removePathFromClients(pfx, p)
return true
}
func (a *AdjRIBOut) removePathsFromClients(pfx net.Prefix, paths []*route.Path) {
for _, path := range paths {
for _, client := range a.ClientManager.Clients() {
client.RemovePath(pfx, path)
}
func (a *AdjRIBOut) isOwnPath(p *route.Path) bool {
if p.Type != a.neighbor.Type {
return false
}
switch p.Type {
case route.BGPPathType:
return p.BGPPath.Source == a.neighbor.Address
}
return false
}
func (a *AdjRIBOut) removePathsFromClients(pfx bnet.Prefix, paths []*route.Path) {
for _, p := range paths {
a.removePathFromClients(pfx, p)
}
}
func (a *AdjRIBOut) removePathFromClients(pfx bnet.Prefix, path *route.Path) {
for _, client := range a.ClientManager.Clients() {
client.RemovePath(pfx, path)
}
}
......
package adjRIBOutAddPath
package adjRIBOut
import (
"fmt"
"github.com/bio-routing/bio-rd/route"
)
var maxUint32 = ^uint32(0)
// pathIDManager manages BGP path identifiers for add-path. This is no thread safe (and doesn't need to be).
type pathIDManager struct {
ids map[uint32]struct{}
last uint32
used uint32
ids map[uint32]uint64
idByPath map[route.BGPPath]uint32
last uint32
used uint32
}
func newPathIDManager() *pathIDManager {
return &pathIDManager{
ids: make(map[uint32]struct{}),
ids: make(map[uint32]uint64),
idByPath: make(map[route.BGPPath]uint32),
}
}
func (fm *pathIDManager) getNewID() (uint32, error) {
func (fm *pathIDManager) addPath(p *route.Path) (uint32, error) {
if _, exists := fm.idByPath[*p.BGPPath]; exists {
id := fm.idByPath[*p.BGPPath]
fm.ids[id]++
return id, nil
}
if fm.used == maxUint32 {
return 0, fmt.Errorf("Out of path IDs")
}
......@@ -33,15 +43,24 @@ func (fm *pathIDManager) getNewID() (uint32, error) {
break
}
ret := fm.last
fm.idByPath[*p.BGPPath] = fm.last
fm.ids[fm.last] = 1
fm.used++
return ret, nil
return fm.last, nil
}
func (fm *pathIDManager) releaseID(id uint32) {
if _, exists := fm.ids[id]; exists {
delete(fm.ids, id)
fm.used--
func (fm *pathIDManager) releasePath(p *route.Path) (uint32, error) {
if _, exists := fm.idByPath[*p.BGPPath]; !exists {
return 0, fmt.Errorf("ID not found for path: %s", p.Print())
}
id := fm.idByPath[*p.BGPPath]
fm.ids[id]--
if fm.ids[id] == 0 {
delete(fm.ids, fm.idByPath[*p.BGPPath])
delete(fm.idByPath, *p.BGPPath)
}
return id, nil
}
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"adj_rib_out_add_path.go",
"path_id_manager.go",
],
importpath = "github.com/bio-routing/bio-rd/routingtable/adjRIBOutAddPath",
visibility = ["//visibility:public"],
deps = [
"//net:go_default_library",
"//route:go_default_library",
"//routingtable: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 = ["//vendor/github.com/stretchr/testify/assert:go_default_library"],
)
package adjRIBOutAddPath
import (
"fmt"
"sync"
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable"
log "github.com/sirupsen/logrus"
)
// AdjRIBOutAddPath represents an Adjacency RIB Out with BGP add path
type AdjRIBOutAddPath struct {
routingtable.ClientManager
rt *routingtable.RoutingTable
neighbor *routingtable.Neighbor
pathIDManager *pathIDManager
mu sync.RWMutex
}
// New creates a new Adjacency RIB Out with BGP add path
func New(neighbor *routingtable.Neighbor) *AdjRIBOutAddPath {
a := &AdjRIBOutAddPath{
rt: routingtable.NewRoutingTable(),
neighbor: neighbor,
pathIDManager: newPathIDManager(),
}
a.ClientManager = routingtable.NewClientManager(a)
return a
}
// UpdateNewClient sends current state to a new client
func (a *AdjRIBOutAddPath) UpdateNewClient(client routingtable.RouteTableClient) error {
return nil
}
// AddPath adds path p to prefix `pfx`
func (a *AdjRIBOutAddPath) AddPath(pfx net.Prefix, p *route.Path) error {
if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
return nil
}
p = p.Copy()
if !a.neighbor.IBGP {
p.BGPPath.ASPath = fmt.Sprintf("%d %s", a.neighbor.LocalASN, p.BGPPath.ASPath)
}
a.mu.Lock()
defer a.mu.Unlock()
pathID, err := a.pathIDManager.getNewID()
if err != nil {
return fmt.Errorf("Unable to get path ID: %v", err)
}
p.BGPPath.PathIdentifier = pathID
a.rt.AddPath(pfx, p)
for _, client := range a.ClientManager.Clients() {
err := client.AddPath(pfx, p)
if err != nil {
log.WithField("Sender", "AdjRIBOutAddPath").WithError(err).Error("Could not send update to client")
}
}
return nil
}
// RemovePath removes the path for prefix `pfx`
func (a *AdjRIBOutAddPath) RemovePath(pfx net.Prefix, p *route.Path) bool {
if !routingtable.ShouldPropagateUpdate(pfx, p, a.neighbor) {
return false
}
a.mu.Lock()
defer a.mu.Unlock()
r := a.rt.Get(pfx)
if r == nil {
return false
}
a.rt.RemovePath(pfx, p)
a.pathIDManager.releaseID(p.BGPPath.PathIdentifier)
a.removePathFromClients(pfx, p)
return true
}
func (a *AdjRIBOutAddPath) isOwnPath(p *route.Path) bool {
if p.Type != a.neighbor.Type {
return false
}
switch p.Type {
case route.BGPPathType:
return p.BGPPath.Source == a.neighbor.Address
}
return false
}
func (a *AdjRIBOutAddPath) removePathFromClients(pfx net.Prefix, path *route.Path) {
for _, client := range a.ClientManager.Clients() {
client.RemovePath(pfx, path)
}
}
// Print dumps all prefixes in the Adj-RIB
func (a *AdjRIBOutAddPath) Print() string {
a.mu.RLock()
defer a.mu.RUnlock()
ret := fmt.Sprintf("DUMPING ADJ-RIB-OUT:\n")
routes := a.rt.Dump()
for _, r := range routes {
ret += fmt.Sprintf("%s\n", r.Prefix().String())
}
return ret
}
package adjRIBOutAddPath
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetNewID(t *testing.T) {
tests := []struct {
name string
maxIDs uint32
count int
wantFail bool
}{
{
name: "Out of path IDs",
maxIDs: 10,
count: 11,
wantFail: true,
},
{
name: "Success",
maxIDs: 10,
count: 10,
wantFail: false,
},
}
X:
for _, test := range tests {
maxUint32 = test.maxIDs
m := newPathIDManager()
for i := 0; i < test.count; i++ {
_, err := m.getNewID()
if err != nil {
if test.wantFail {
continue X
}
t.Errorf("Unexpected failure for test %q: %v", test.name, err)
continue X
}
}
if test.wantFail {
t.Errorf("Unexpected success for test %q", test.name)
continue
}
}
}
func TestReleaseID(t *testing.T) {
tests := []struct {
name string
pm *pathIDManager
release uint32
expected *pathIDManager
}{
{
name: "Release existent",
pm: &pathIDManager{
ids: map[uint32]struct{}{
0: struct{}{},
1: struct{}{},
2: struct{}{},
},
last: 2,
used: 3,
},
release: 1,
expected: &pathIDManager{
ids: map[uint32]struct{}{
0: struct{}{},
2: struct{}{},
},
last: 2,
used: 2,
},
},
{
name: "Release non-existent",
pm: &pathIDManager{
ids: map[uint32]struct{}{
0: struct{}{},
1: struct{}{},
2: struct{}{},
},
last: 2,
used: 3,
},
release: 3,
expected: &pathIDManager{
ids: map[uint32]struct{}{
0: struct{}{},
1: struct{}{},
2: struct{}{},
},
last: 2,
used: 3,
},
},
}
for _, test := range tests {
test.pm.releaseID(test.release)
assert.Equalf(t, test.expected, test.pm, "%s", test.name)
}
}
......@@ -19,7 +19,6 @@ go_library(
"//net:go_default_library",
"//protocols/bgp/packet:go_default_library",
"//route:go_default_library",
"//routingtable:go_default_library",
"//routingtable/filter/actions:go_default_library",
],
)
......@@ -38,7 +37,6 @@ go_test(
"//net:go_default_library",
"//protocols/bgp/packet:go_default_library",
"//route:go_default_library",
"//routingtable:go_default_library",
"//routingtable/filter/actions:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
],
......
......@@ -3,11 +3,9 @@ package filter
import (
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable"
)
type Filter struct {
routingtable.ClientManager
terms []*Term
}
......@@ -15,42 +13,11 @@ func NewFilter(terms []*Term) *Filter {
f := &Filter{
terms: terms,
}
f.ClientManager = routingtable.NewClientManager(f)
return f
}
func (f *Filter) AddPath(p net.Prefix, pa *route.Path) error {
pa, rejected := f.processTerms(p, pa)
if rejected {
return nil
}
for _, c := range f.Clients() {
c.AddPath(p, pa)
}
return nil
}
func (f *Filter) RemovePath(p net.Prefix, pa *route.Path) bool {
pa, rejected := f.processTerms(p, pa)
if rejected {
return false
}
for _, c := range f.Clients() {
c.RemovePath(p, pa)
}
return true
}
func (f *Filter) UpdateNewClient(c routingtable.RouteTableClient) error {
return nil
}
func (f *Filter) processTerms(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) {
func (f *Filter) ProcessTerms(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) {
modPath = pa
for _, t := range f.terms {
......
package filter
import (
"testing"
"github.com/bio-routing/bio-rd/routingtable/filter/actions"
"github.com/stretchr/testify/assert"
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable"
)
type clientMock struct {
routingtable.ClientManager
addPathCalled bool
removePathCalled bool
path *route.Path
}
func (m *clientMock) AddPath(p net.Prefix, pa *route.Path) error {
m.path = pa
m.addPathCalled = true
return nil
}
func (m *clientMock) RemovePath(p net.Prefix, pa *route.Path) bool {
m.path = pa
m.removePathCalled = true
return false
}
func (m *clientMock) UpdateNewClient(c routingtable.RouteTableClient) error {
return nil
}
func newClientMock() *clientMock {
m := &clientMock{}
m.ClientManager = routingtable.NewClientManager(m)
return m
}
func TestAddPath(t *testing.T) {
/*func TestAddPath(t *testing.T) {
tests := []struct {
name string
prefix net.Prefix
......@@ -184,4 +144,4 @@ func TestRemovePath(t *testing.T) {
}
})
}
}
}*/
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment