Skip to content
Snippets Groups Projects
Commit f069e762 authored by Oliver Herms's avatar Oliver Herms
Browse files

Implemented Route Server support

parent 3edbc74a
No related branches found
No related tags found
No related merge requests found
Showing with 82 additions and 501 deletions
...@@ -23,4 +23,5 @@ type Peer struct { ...@@ -23,4 +23,5 @@ type Peer struct {
AddPathRecv bool AddPathRecv bool
ImportFilter *filter.Filter ImportFilter *filter.Filter
ExportFilter *filter.Filter ExportFilter *filter.Filter
RouteServerClient bool
} }
...@@ -53,8 +53,9 @@ func main() { ...@@ -53,8 +53,9 @@ func main() {
AddPathSend: routingtable.ClientOptions{ AddPathSend: routingtable.ClientOptions{
MaxPaths: 10, MaxPaths: 10,
}, },
ImportFilter: filter.NewDrainFilter(), ImportFilter: filter.NewDrainFilter(),
ExportFilter: filter.NewAcceptAllFilter(), ExportFilter: filter.NewAcceptAllFilter(),
RouteServerClient: true,
}, rib) }, rib)
b.AddPeer(config.Peer{ b.AddPeer(config.Peer{
...@@ -71,9 +72,10 @@ func main() { ...@@ -71,9 +72,10 @@ func main() {
AddPathSend: routingtable.ClientOptions{ AddPathSend: routingtable.ClientOptions{
MaxPaths: 10, MaxPaths: 10,
}, },
AddPathRecv: true, AddPathRecv: true,
ImportFilter: filter.NewAcceptAllFilter(), ImportFilter: filter.NewAcceptAllFilter(),
ExportFilter: filter.NewDrainFilter(), ExportFilter: filter.NewDrainFilter(),
RouteServerClient: true,
}, rib) }, rib)
go func() { go func() {
......
...@@ -3,14 +3,14 @@ package server ...@@ -3,14 +3,14 @@ package server
import ( import (
"bytes" "bytes"
"fmt" "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/protocols/bgp/packet"
"github.com/bio-routing/bio-rd/route" "github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable" "github.com/bio-routing/bio-rd/routingtable"
"github.com/bio-routing/bio-rd/routingtable/adjRIBIn" "github.com/bio-routing/bio-rd/routingtable/adjRIBIn"
"github.com/bio-routing/bio-rd/routingtable/adjRIBOut" "github.com/bio-routing/bio-rd/routingtable/adjRIBOut"
"github.com/bio-routing/bio-rd/routingtable/adjRIBOutAddPath"
) )
type establishedState struct { type establishedState struct {
...@@ -25,7 +25,10 @@ func newEstablishedState(fsm *FSM) *establishedState { ...@@ -25,7 +25,10 @@ func newEstablishedState(fsm *FSM) *establishedState {
func (s establishedState) run() (state, string) { func (s establishedState) run() (state, string) {
if !s.fsm.ribsInitialized { if !s.fsm.ribsInitialized {
s.init() err := s.init()
if err != nil {
return newCeaseState(), fmt.Sprintf("Init failed: %v", err)
}
} }
for { for {
...@@ -51,45 +54,51 @@ func (s establishedState) run() (state, string) { ...@@ -51,45 +54,51 @@ func (s establishedState) run() (state, string) {
} }
} }
func (s *establishedState) init() { func (s *establishedState) init() error {
s.fsm.adjRIBIn = adjRIBIn.New() s.fsm.adjRIBIn = adjRIBIn.New(s.fsm.peer.importFilter)
s.fsm.adjRIBIn.Register(s.fsm.rib)
s.fsm.peer.importFilter.Register(s.fsm.rib) host, _, err := net.SplitHostPort(s.fsm.con.LocalAddr().String())
s.fsm.adjRIBIn.Register(s.fsm.peer.importFilter) 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{ n := &routingtable.Neighbor{
Type: route.BGPPathType, Type: route.BGPPathType,
Address: tnet.IPv4ToUint32(s.fsm.peer.addr), Address: bnet.IPv4ToUint32(s.fsm.peer.addr),
IBGP: s.fsm.peer.localASN == s.fsm.peer.peerASN, IBGP: s.fsm.peer.localASN == s.fsm.peer.peerASN,
LocalASN: s.fsm.peer.localASN, 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{ clientOptions := routingtable.ClientOptions{
BestOnly: true, BestOnly: true,
} }
if s.fsm.capAddPathSend { if s.fsm.capAddPathSend {
s.fsm.updateSender = newUpdateSenderAddPath(s.fsm) s.fsm.updateSender = newUpdateSenderAddPath(s.fsm)
s.fsm.adjRIBOut = adjRIBOutAddPath.New(n)
clientOptions = s.fsm.peer.addPathSend clientOptions = s.fsm.peer.addPathSend
} else { } else {
s.fsm.updateSender = newUpdateSender(s.fsm) s.fsm.updateSender = newUpdateSender(s.fsm)
s.fsm.adjRIBOut = adjRIBOut.New(n)
} }
s.fsm.adjRIBOut.Register(s.fsm.updateSender) s.fsm.adjRIBOut.Register(s.fsm.updateSender)
s.fsm.peer.exportFilter.Register(s.fsm.adjRIBOut) s.fsm.rib.RegisterWithOptions(s.fsm.adjRIBOut, clientOptions)
s.fsm.rib.RegisterWithOptions(s.fsm.peer.exportFilter, clientOptions)
s.fsm.ribsInitialized = true s.fsm.ribsInitialized = true
return nil
} }
func (s *establishedState) uninit() { func (s *establishedState) uninit() {
s.fsm.adjRIBIn.Unregister(s.fsm.peer.importFilter) s.fsm.adjRIBIn.Unregister(s.fsm.rib)
s.fsm.peer.importFilter.Unregister(s.fsm.rib) s.fsm.rib.Unregister(s.fsm.adjRIBOut)
s.fsm.adjRIBOut.Unregister(s.fsm.updateSender)
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 = nil s.fsm.adjRIBIn = nil
s.fsm.adjRIBOut = nil s.fsm.adjRIBOut = nil
...@@ -190,19 +199,19 @@ func (s *establishedState) update(msg *packet.BGPMessage) (state, string) { ...@@ -190,19 +199,19 @@ func (s *establishedState) update(msg *packet.BGPMessage) (state, string) {
func (s *establishedState) withdraws(u *packet.BGPUpdate) { func (s *establishedState) withdraws(u *packet.BGPUpdate) {
for r := u.WithdrawnRoutes; r != nil; r = r.Next { 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) s.fsm.adjRIBIn.RemovePath(pfx, nil)
} }
} }
func (s *establishedState) updates(u *packet.BGPUpdate) { func (s *establishedState) updates(u *packet.BGPUpdate) {
for r := u.NLRI; r != nil; r = r.Next { 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{ path := &route.Path{
Type: route.BGPPathType, Type: route.BGPPathType,
BGPPath: &route.BGPPath{ BGPPath: &route.BGPPath{
Source: tnet.IPv4ToUint32(s.fsm.peer.addr), Source: bnet.IPv4ToUint32(s.fsm.peer.addr),
}, },
} }
......
...@@ -28,6 +28,7 @@ type Peer struct { ...@@ -28,6 +28,7 @@ type Peer struct {
optOpenParams []packet.OptParam optOpenParams []packet.OptParam
importFilter *filter.Filter importFilter *filter.Filter
exportFilter *filter.Filter exportFilter *filter.Filter
routeServerClient bool
} }
func (p *Peer) collisionHandling(callingFSM *FSM) bool { func (p *Peer) collisionHandling(callingFSM *FSM) bool {
...@@ -98,6 +99,7 @@ func NewPeer(c config.Peer, rib routingtable.RouteTableClient, server *BGPServer ...@@ -98,6 +99,7 @@ func NewPeer(c config.Peer, rib routingtable.RouteTableClient, server *BGPServer
optOpenParams: make([]packet.OptParam, 0), optOpenParams: make([]packet.OptParam, 0),
importFilter: filterOrDefault(c.ImportFilter), importFilter: filterOrDefault(c.ImportFilter),
exportFilter: filterOrDefault(c.ExportFilter), exportFilter: filterOrDefault(c.ExportFilter),
routeServerClient: c.RouteServerClient,
} }
p.fsms = append(p.fsms, NewActiveFSM2(p)) p.fsms = append(p.fsms, NewActiveFSM2(p))
......
...@@ -3,6 +3,8 @@ package adjRIBIn ...@@ -3,6 +3,8 @@ package adjRIBIn
import ( import (
"sync" "sync"
"github.com/bio-routing/bio-rd/routingtable/filter"
"github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route" "github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable" "github.com/bio-routing/bio-rd/routingtable"
...@@ -12,14 +14,16 @@ import ( ...@@ -12,14 +14,16 @@ import (
// AdjRIBIn represents an Adjacency RIB In as described in RFC4271 // AdjRIBIn represents an Adjacency RIB In as described in RFC4271
type AdjRIBIn struct { type AdjRIBIn struct {
routingtable.ClientManager routingtable.ClientManager
rt *routingtable.RoutingTable rt *routingtable.RoutingTable
mu sync.RWMutex mu sync.RWMutex
exportFilter *filter.Filter
} }
// New creates a new Adjacency RIB In // New creates a new Adjacency RIB In
func New() *AdjRIBIn { func New(exportFilter *filter.Filter) *AdjRIBIn {
a := &AdjRIBIn{ a := &AdjRIBIn{
rt: routingtable.NewRoutingTable(), rt: routingtable.NewRoutingTable(),
exportFilter: exportFilter,
} }
a.ClientManager = routingtable.NewClientManager(a) a.ClientManager = routingtable.NewClientManager(a)
return a return a
...@@ -34,6 +38,10 @@ func (a *AdjRIBIn) UpdateNewClient(client routingtable.RouteTableClient) error { ...@@ -34,6 +38,10 @@ func (a *AdjRIBIn) UpdateNewClient(client routingtable.RouteTableClient) error {
for _, route := range routes { for _, route := range routes {
paths := route.Paths() paths := route.Paths()
for _, path := range paths { for _, path := range paths {
path, reject := a.exportFilter.ProcessTerms(route.Prefix(), path)
if reject {
continue
}
err := client.AddPath(route.Prefix(), path) err := client.AddPath(route.Prefix(), path)
if err != nil { if err != nil {
...@@ -52,6 +60,11 @@ func (a *AdjRIBIn) AddPath(pfx net.Prefix, p *route.Path) error { ...@@ -52,6 +60,11 @@ func (a *AdjRIBIn) AddPath(pfx net.Prefix, p *route.Path) error {
oldPaths := a.rt.ReplacePath(pfx, p) oldPaths := a.rt.ReplacePath(pfx, p)
a.removePathsFromClients(pfx, oldPaths) a.removePathsFromClients(pfx, oldPaths)
p, reject := a.exportFilter.ProcessTerms(pfx, p)
if reject {
return nil
}
for _, client := range a.ClientManager.Clients() { for _, client := range a.ClientManager.Clients() {
client.AddPath(pfx, p) client.AddPath(pfx, p)
} }
...@@ -79,6 +92,10 @@ func (a *AdjRIBIn) RemovePath(pfx net.Prefix, p *route.Path) bool { ...@@ -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) { func (a *AdjRIBIn) removePathsFromClients(pfx net.Prefix, paths []*route.Path) {
for _, path := range paths { for _, path := range paths {
path, reject := a.exportFilter.ProcessTerms(pfx, path)
if reject {
continue
}
for _, client := range a.ClientManager.Clients() { for _, client := range a.ClientManager.Clients() {
client.RemovePath(pfx, path) client.RemovePath(pfx, path)
} }
......
...@@ -4,6 +4,8 @@ import ( ...@@ -4,6 +4,8 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/bio-routing/bio-rd/routingtable/filter"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/net"
...@@ -113,7 +115,7 @@ func TestAddPath(t *testing.T) { ...@@ -113,7 +115,7 @@ func TestAddPath(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
adjRIBIn := New() adjRIBIn := New(filter.NewAcceptAllFilter())
mc := NewRTMockClient() mc := NewRTMockClient()
adjRIBIn.ClientManager.Register(mc) adjRIBIn.ClientManager.Register(mc)
...@@ -204,7 +206,7 @@ func TestRemovePath(t *testing.T) { ...@@ -204,7 +206,7 @@ func TestRemovePath(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
adjRIBIn := New() adjRIBIn := New(filter.NewAcceptAllFilter())
for _, route := range test.routes { for _, route := range test.routes {
adjRIBIn.AddPath(route.Prefix(), route.Paths()[0]) adjRIBIn.AddPath(route.Prefix(), route.Paths()[0])
} }
......
package adjRIBOut
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"
)
// AdjRIBOut represents an Adjacency RIB In as described in RFC4271
type AdjRIBOut struct {
routingtable.ClientManager
rt *routingtable.RoutingTable
neighbor *routingtable.Neighbor
mu sync.RWMutex
}
// New creates a new Adjacency RIB In
func New(neighbor *routingtable.Neighbor) *AdjRIBOut {
a := &AdjRIBOut{
rt: routingtable.NewRoutingTable(),
neighbor: neighbor,
}
a.ClientManager = routingtable.NewClientManager(a)
return a
}
// UpdateNewClient sends current state to a new client
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 {
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()
oldPaths := a.rt.ReplacePath(pfx, p)
a.removePathsFromClients(pfx, oldPaths)
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")
}
}
return nil
}
// RemovePath removes the path for prefix `pfx`
func (a *AdjRIBOut) 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
}
oldPaths := r.Paths()
for _, path := range oldPaths {
a.rt.RemovePath(pfx, path)
}
a.removePathsFromClients(pfx, oldPaths)
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)
}
}
}
// Print dumps all prefixes in the Adj-RIB
func (a *AdjRIBOut) 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 (
"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 (
"fmt"
)
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
}
func newPathIDManager() *pathIDManager {
return &pathIDManager{
ids: make(map[uint32]struct{}),
}
}
func (fm *pathIDManager) getNewID() (uint32, error) {
if fm.used == maxUint32 {
return 0, fmt.Errorf("Out of path IDs")
}
fm.last++
for {
if _, exists := fm.ids[fm.last]; exists {
fm.last++
continue
}
break
}
ret := fm.last
fm.used++
return ret, nil
}
func (fm *pathIDManager) releaseID(id uint32) {
if _, exists := fm.ids[id]; exists {
delete(fm.ids, id)
fm.used--
}
}
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)
}
}
...@@ -3,11 +3,9 @@ package filter ...@@ -3,11 +3,9 @@ package filter
import ( import (
"github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route" "github.com/bio-routing/bio-rd/route"
"github.com/bio-routing/bio-rd/routingtable"
) )
type Filter struct { type Filter struct {
routingtable.ClientManager
terms []*Term terms []*Term
} }
...@@ -15,42 +13,11 @@ func NewFilter(terms []*Term) *Filter { ...@@ -15,42 +13,11 @@ func NewFilter(terms []*Term) *Filter {
f := &Filter{ f := &Filter{
terms: terms, terms: terms,
} }
f.ClientManager = routingtable.NewClientManager(f)
return f return f
} }
func (f *Filter) AddPath(p net.Prefix, pa *route.Path) error { func (f *Filter) ProcessTerms(p net.Prefix, pa *route.Path) (modPath *route.Path, reject bool) {
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) {
modPath = pa modPath = pa
for _, t := range f.terms { for _, t := range f.terms {
......
package filter package filter
import ( /*func TestAddPath(t *testing.T) {
"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) {
tests := []struct { tests := []struct {
name string name string
prefix net.Prefix prefix net.Prefix
...@@ -184,4 +144,4 @@ func TestRemovePath(t *testing.T) { ...@@ -184,4 +144,4 @@ func TestRemovePath(t *testing.T) {
} }
}) })
} }
} }*/
package filter package filter
import ( /*func TestNewAcceptAllFilter(t *testing.T) {
"testing"
"github.com/bio-routing/bio-rd/net"
"github.com/bio-routing/bio-rd/route"
)
func TestNewAcceptAllFilter(t *testing.T) {
f := NewAcceptAllFilter() f := NewAcceptAllFilter()
m := &clientMock{} m := &clientMock{}
...@@ -31,4 +24,4 @@ func TestNewDrainFilter(t *testing.T) { ...@@ -31,4 +24,4 @@ func TestNewDrainFilter(t *testing.T) {
if m.addPathCalled { if m.addPathCalled {
t.Fatalf("expected filtered, but was accepted") t.Fatalf("expected filtered, but was accepted")
} }
} }*/
...@@ -5,6 +5,9 @@ type Neighbor struct { ...@@ -5,6 +5,9 @@ type Neighbor struct {
// Addres is the IPv4 address of the neighbor as integer representation // Addres is the IPv4 address of the neighbor as integer representation
Address uint32 Address uint32
// Local address is the local address of the BGP TCP connection
LocalAddress uint32
// Type is the type / protocol used for routing inforation communitation // Type is the type / protocol used for routing inforation communitation
Type uint8 Type uint8
...@@ -13,4 +16,10 @@ type Neighbor struct { ...@@ -13,4 +16,10 @@ type Neighbor struct {
// Local ASN of session // Local ASN of session
LocalASN uint32 LocalASN uint32
// Peer is a route server client
RouteServerClient bool
// CapAddPathRX indicates if the peer supports receiving multiple BGP paths
CapAddPathRX bool
} }
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