diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go index aaf1b744008c1d3df14a10ff2bc57573a636aa9d..e95a4f817e128960ce704443bde1313562745656 100644 --- a/protocols/bgp/server/update_sender.go +++ b/protocols/bgp/server/update_sender.go @@ -16,7 +16,7 @@ import ( // UpdateSender converts table changes into BGP update messages type UpdateSender struct { - routingtable.ClientManager + clientManager *routingtable.ClientManager fsm *FSM addressFamily *fsmAddressFamily options *packet.EncodeOptions @@ -35,7 +35,7 @@ type pathPfxs struct { func newUpdateSender(fsm *FSM, afi uint16, safi uint8) *UpdateSender { f := fsm.addressFamily(afi, safi) - return &UpdateSender{ + u := &UpdateSender{ fsm: fsm, addressFamily: f, iBGP: fsm.peer.localASN == fsm.peer.peerASN, @@ -47,6 +47,9 @@ func newUpdateSender(fsm *FSM, afi uint16, safi uint8) *UpdateSender { UseAddPath: !f.addPathTX.BestOnly, }, } + u.clientManager = routingtable.NewClientManager(u) + + return u } // Start starts the update sender @@ -335,3 +338,18 @@ func (u *UpdateSender) RouteCount() int64 { log.Warningf("BGP Update Sender: RouteCount not implemented") return 0 } + +// Register registers a client for updates +func (a *UpdateSender) Register(client routingtable.RouteTableClient) { + a.clientManager.RegisterWithOptions(client, routingtable.ClientOptions{BestOnly: true}) +} + +// RegisterWithOptions registers a client with options for updates +func (a *UpdateSender) RegisterWithOptions(client routingtable.RouteTableClient, opt routingtable.ClientOptions) { + a.clientManager.RegisterWithOptions(client, opt) +} + +// Unregister unregisters a client +func (a *UpdateSender) Unregister(client routingtable.RouteTableClient) { + a.clientManager.Unregister(client) +} diff --git a/routingtable/adjRIBIn/adj_rib_in.go b/routingtable/adjRIBIn/adj_rib_in.go index 5bf7862334ece9b649baf5c75e42eff4936689f9..3fa6e7acf22a30202e18950b7028f6a47251fe6d 100644 --- a/routingtable/adjRIBIn/adj_rib_in.go +++ b/routingtable/adjRIBIn/adj_rib_in.go @@ -3,17 +3,16 @@ 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" + "github.com/bio-routing/bio-rd/routingtable/filter" log "github.com/sirupsen/logrus" ) // AdjRIBIn represents an Adjacency RIB In as described in RFC4271 type AdjRIBIn struct { - routingtable.ClientManager + clientManager *routingtable.ClientManager rt *routingtable.RoutingTable mu sync.RWMutex exportFilter *filter.Filter @@ -33,7 +32,7 @@ func New(exportFilter *filter.Filter, contributingASNs *routingtable.Contributin clusterID: clusterID, addPathRX: addPathRX, } - a.ClientManager = routingtable.NewClientManager(a) + a.clientManager = routingtable.NewClientManager(a) return a } @@ -114,7 +113,7 @@ func (a *AdjRIBIn) AddPath(pfx net.Prefix, p *route.Path) error { return nil } - for _, client := range a.ClientManager.Clients() { + for _, client := range a.clientManager.Clients() { client.AddPath(pfx, p) } return nil @@ -170,7 +169,7 @@ func (a *AdjRIBIn) removePathsFromClients(pfx net.Prefix, paths []*route.Path) { if reject { continue } - for _, client := range a.ClientManager.Clients() { + for _, client := range a.clientManager.Clients() { client.RemovePath(pfx, path) } } @@ -179,3 +178,13 @@ func (a *AdjRIBIn) removePathsFromClients(pfx net.Prefix, paths []*route.Path) { func (a *AdjRIBIn) RT() *routingtable.RoutingTable { return a.rt } + +// Register registers a client for updates +func (a *AdjRIBIn) Register(client routingtable.RouteTableClient) { + a.clientManager.RegisterWithOptions(client, routingtable.ClientOptions{BestOnly: true}) +} + +// Unregister unregisters a client +func (a *AdjRIBIn) Unregister(client routingtable.RouteTableClient) { + a.clientManager.Unregister(client) +} diff --git a/routingtable/adjRIBIn/adj_rib_in_test.go b/routingtable/adjRIBIn/adj_rib_in_test.go index 76bbc90d23b8d9974819648c3921cb2ee99fdee2..acd8a53bd8a3ea8d18c072b93fbe4cd1afd0a95c 100644 --- a/routingtable/adjRIBIn/adj_rib_in_test.go +++ b/routingtable/adjRIBIn/adj_rib_in_test.go @@ -3,12 +3,11 @@ package adjRIBIn import ( "testing" - "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" "github.com/bio-routing/bio-rd/routingtable/filter" + "github.com/stretchr/testify/assert" ) func TestAddPath(t *testing.T) { @@ -146,7 +145,7 @@ func TestAddPath(t *testing.T) { for _, test := range tests { adjRIBIn := New(filter.NewAcceptAllFilter(), routingtable.NewContributingASNs(), routerID, clusterID, test.addPath) mc := routingtable.NewRTMockClient() - adjRIBIn.ClientManager.Register(mc) + adjRIBIn.clientManager.RegisterWithOptions(mc, routingtable.ClientOptions{BestOnly: true}) for _, route := range test.routes { adjRIBIn.AddPath(route.Prefix(), route.Paths()[0]) @@ -293,7 +292,7 @@ func TestRemovePath(t *testing.T) { } mc := routingtable.NewRTMockClient() - adjRIBIn.ClientManager.Register(mc) + adjRIBIn.clientManager.RegisterWithOptions(mc, routingtable.ClientOptions{}) adjRIBIn.RemovePath(test.removePfx, test.removePath) if test.wantPropagation { diff --git a/routingtable/adjRIBOut/adj_rib_out.go b/routingtable/adjRIBOut/adj_rib_out.go index 289dc7da1202cafd259aa93aa24f69b8f0e784fc..c9a0bb90090bd3870a646684959c310e513d0d62 100644 --- a/routingtable/adjRIBOut/adj_rib_out.go +++ b/routingtable/adjRIBOut/adj_rib_out.go @@ -4,17 +4,16 @@ import ( "fmt" "sync" + bnet "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 Out with BGP add path type AdjRIBOut struct { - routingtable.ClientManager + clientManager *routingtable.ClientManager rt *routingtable.RoutingTable neighbor *routingtable.Neighbor addPathTX bool @@ -32,7 +31,7 @@ func New(neighbor *routingtable.Neighbor, exportFilter *filter.Filter, addPathTX exportFilter: exportFilter, addPathTX: addPathTX, } - a.ClientManager = routingtable.NewClientManager(a) + a.clientManager = routingtable.NewClientManager(a) return a } @@ -110,7 +109,7 @@ func (a *AdjRIBOut) AddPath(pfx bnet.Prefix, p *route.Path) error { a.removePathsFromClients(pfx, oldPaths) } - for _, client := range a.ClientManager.Clients() { + 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") @@ -204,7 +203,7 @@ func (a *AdjRIBOut) removePathsFromClients(pfx bnet.Prefix, paths []*route.Path) } func (a *AdjRIBOut) removePathFromClients(pfx bnet.Prefix, path *route.Path) { - for _, client := range a.ClientManager.Clients() { + for _, client := range a.clientManager.Clients() { client.RemovePath(pfx, path) } } @@ -236,3 +235,13 @@ func (a *AdjRIBOut) Dump() string { return ret } + +// Register registers a client for updates +func (a *AdjRIBOut) Register(client routingtable.RouteTableClient) { + a.clientManager.RegisterWithOptions(client, routingtable.ClientOptions{BestOnly: true}) +} + +// Unregister unregisters a client +func (a *AdjRIBOut) Unregister(client routingtable.RouteTableClient) { + a.clientManager.Unregister(client) +} diff --git a/routingtable/client_interface.go b/routingtable/client_interface.go index 536a76020ca6276d22536ebd3781685356dc3738..6304d3e1cecfef7d4f5c960b6eb0824b5a8c6bd4 100644 --- a/routingtable/client_interface.go +++ b/routingtable/client_interface.go @@ -11,7 +11,6 @@ type RouteTableClient interface { RemovePath(net.Prefix, *route.Path) bool UpdateNewClient(RouteTableClient) error Register(RouteTableClient) - RegisterWithOptions(RouteTableClient, ClientOptions) Unregister(RouteTableClient) RouteCount() int64 } diff --git a/routingtable/client_manager.go b/routingtable/client_manager.go index b779bb0ba049f1d1f51de9fa8e70f27056fdb61e..824f1151491aaf9d85535c8e82374f38a69aa7f2 100644 --- a/routingtable/client_manager.go +++ b/routingtable/client_manager.go @@ -32,8 +32,8 @@ type ClientManager struct { } // NewClientManager creates and initializes a new client manager -func NewClientManager(master RouteTableClient) ClientManager { - return ClientManager{ +func NewClientManager(master RouteTableClient) *ClientManager { + return &ClientManager{ clients: make(map[RouteTableClient]ClientOptions, 0), master: master, } @@ -47,11 +47,6 @@ func (c *ClientManager) GetOptions(client RouteTableClient) ClientOptions { return c.clients[client] } -// Register registers a client for updates -func (c *ClientManager) Register(client RouteTableClient) { - c.RegisterWithOptions(client, ClientOptions{BestOnly: true}) -} - // RegisterWithOptions registers a client with options for updates func (c *ClientManager) RegisterWithOptions(client RouteTableClient, opt ClientOptions) { c.mu.Lock() @@ -62,13 +57,14 @@ func (c *ClientManager) RegisterWithOptions(client RouteTableClient, opt ClientO } // Unregister unregisters a client -func (c *ClientManager) Unregister(client RouteTableClient) { +func (c *ClientManager) Unregister(client RouteTableClient) bool { c.mu.Lock() defer c.mu.Unlock() if _, ok := c.clients[client]; !ok { - return + return false } delete(c.clients, client) + return true } // Clients returns a list of registered clients diff --git a/routingtable/client_manager_test.go b/routingtable/client_manager_test.go index 0106c69263224c16ba867e46e63e4027ce0b4434..28328e4c335cdddd310699ef54959b3455b871c7 100644 --- a/routingtable/client_manager_test.go +++ b/routingtable/client_manager_test.go @@ -3,10 +3,9 @@ package routingtable import ( "testing" - "github.com/stretchr/testify/assert" - "github.com/bio-routing/bio-rd/net" "github.com/bio-routing/bio-rd/route" + "github.com/stretchr/testify/assert" ) type MockClient struct { @@ -26,10 +25,6 @@ func (m MockClient) Register(RouteTableClient) { return } -func (m MockClient) RegisterWithOptions(RouteTableClient, ClientOptions) { - return -} - func (m MockClient) Unregister(RouteTableClient) { return } @@ -73,7 +68,7 @@ func TestClients(t *testing.T) { for _, test := range tests { cm := NewClientManager(MockClient{}) for _, client := range test.clients { - cm.Register(client) + cm.RegisterWithOptions(client, ClientOptions{}) } ret := cm.Clients() diff --git a/routingtable/locRIB/loc_rib.go b/routingtable/locRIB/loc_rib.go index aa60b9243aab1846bdb6dd010f9ced6155071268..1c7935e41b9d55912e8a240c1f22afaa18f1616e 100644 --- a/routingtable/locRIB/loc_rib.go +++ b/routingtable/locRIB/loc_rib.go @@ -13,7 +13,7 @@ import ( // LocRIB represents a routing information base type LocRIB struct { - routingtable.ClientManager + clientManager *routingtable.ClientManager rt *routingtable.RoutingTable mu sync.RWMutex contributingASNs *routingtable.ContributingASNs @@ -25,7 +25,7 @@ func New() *LocRIB { rt: routingtable.NewRoutingTable(), contributingASNs: routingtable.NewContributingASNs(), } - a.ClientManager = routingtable.NewClientManager(a) + a.clientManager = routingtable.NewClientManager(a) return a } @@ -122,8 +122,8 @@ func (a *LocRIB) propagateChanges(oldRoute *route.Route, newRoute *route.Route) } func (a *LocRIB) addPathsToClients(oldRoute *route.Route, newRoute *route.Route) { - for _, client := range a.ClientManager.Clients() { - opts := a.ClientManager.GetOptions(client) + for _, client := range a.clientManager.Clients() { + opts := a.clientManager.GetOptions(client) oldMaxPaths := opts.GetMaxPaths(oldRoute.ECMPPathCount()) newMaxPaths := opts.GetMaxPaths(newRoute.ECMPPathCount()) @@ -139,8 +139,8 @@ func (a *LocRIB) addPathsToClients(oldRoute *route.Route, newRoute *route.Route) } func (a *LocRIB) removePathsFromClients(oldRoute *route.Route, newRoute *route.Route) { - for _, client := range a.ClientManager.Clients() { - opts := a.ClientManager.GetOptions(client) + for _, client := range a.clientManager.Clients() { + opts := a.clientManager.GetOptions(client) oldMaxPaths := opts.GetMaxPaths(oldRoute.ECMPPathCount()) newMaxPaths := opts.GetMaxPaths(newRoute.ECMPPathCount()) @@ -187,3 +187,18 @@ func (a *LocRIB) Print() string { return ret } + +// Register registers a client for updates +func (a *LocRIB) Register(client routingtable.RouteTableClient) { + a.clientManager.RegisterWithOptions(client, routingtable.ClientOptions{BestOnly: true}) +} + +// RegisterWithOptions registers a client with options for updates +func (a *LocRIB) RegisterWithOptions(client routingtable.RouteTableClient, opt routingtable.ClientOptions) { + a.clientManager.RegisterWithOptions(client, opt) +} + +// Unregister unregisters a client +func (a *LocRIB) Unregister(client routingtable.RouteTableClient) { + a.clientManager.Unregister(client) +}