Merge pull request #835 from milosgajdos83/router-strategy
Router strategy
This commit is contained in:
commit
5a6e73d4a8
@ -319,23 +319,13 @@ func (r *router) advertiseTable() error {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
// list routing table routes to announce
|
||||
routes, err := r.table.List()
|
||||
// do full table flush
|
||||
events, err := r.flushRouteEvents(Update)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed listing routes: %s", err)
|
||||
}
|
||||
// collect all the added routes before we attempt to add default gateway
|
||||
events := make([]*Event, len(routes))
|
||||
for i, route := range routes {
|
||||
event := &Event{
|
||||
Type: Update,
|
||||
Timestamp: time.Now(),
|
||||
Route: route,
|
||||
}
|
||||
events[i] = event
|
||||
return fmt.Errorf("failed flushing routes: %s", err)
|
||||
}
|
||||
|
||||
// advertise all routes as Update events to subscribers
|
||||
// advertise routes to subscribers
|
||||
if len(events) > 0 {
|
||||
log.Debugf("Router flushing table with %d events: %s", len(events), r.options.Id)
|
||||
r.advertWg.Add(1)
|
||||
@ -692,15 +682,58 @@ func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) {
|
||||
return nil, fmt.Errorf("failed listing routes: %s", err)
|
||||
}
|
||||
|
||||
if r.options.Advertise == AdvertiseAll {
|
||||
// build a list of events to advertise
|
||||
events := make([]*Event, len(routes))
|
||||
for i, route := range routes {
|
||||
event := &Event{
|
||||
Type: evType,
|
||||
Timestamp: time.Now(),
|
||||
Route: route,
|
||||
}
|
||||
events[i] = event
|
||||
}
|
||||
return events, nil
|
||||
}
|
||||
|
||||
// routeMap stores optimal routes per service
|
||||
bestRoutes := make(map[string]Route)
|
||||
|
||||
// go through all routes found in the routing table and collapse them to optimal routes
|
||||
for _, route := range routes {
|
||||
routeKey := route.Service + "@" + route.Network
|
||||
optimal, ok := bestRoutes[routeKey]
|
||||
if !ok {
|
||||
bestRoutes[routeKey] = route
|
||||
continue
|
||||
}
|
||||
// if the current optimal route metric is higher than routing table route, replace it
|
||||
if optimal.Metric > route.Metric {
|
||||
bestRoutes[routeKey] = route
|
||||
continue
|
||||
}
|
||||
// if the metrics are the same, prefer advertising your own route
|
||||
if optimal.Metric == route.Metric {
|
||||
if route.Router == r.options.Id {
|
||||
bestRoutes[routeKey] = route
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("Router advertising %d best routes out of %d", len(bestRoutes), len(routes))
|
||||
|
||||
// build a list of events to advertise
|
||||
events := make([]*Event, len(routes))
|
||||
for i, route := range routes {
|
||||
events := make([]*Event, len(bestRoutes))
|
||||
i := 0
|
||||
for _, route := range bestRoutes {
|
||||
event := &Event{
|
||||
Type: evType,
|
||||
Timestamp: time.Now(),
|
||||
Route: route,
|
||||
}
|
||||
events[i] = event
|
||||
i++
|
||||
}
|
||||
|
||||
return events, nil
|
||||
|
@ -18,6 +18,8 @@ type Options struct {
|
||||
Network string
|
||||
// Registry is the local registry
|
||||
Registry registry.Registry
|
||||
// Advertise is the advertising strategy
|
||||
Advertise Strategy
|
||||
// Client for calling router
|
||||
Client client.Client
|
||||
}
|
||||
@ -64,12 +66,20 @@ func Registry(r registry.Registry) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// Strategy sets route advertising strategy
|
||||
func Advertise(a Strategy) Option {
|
||||
return func(o *Options) {
|
||||
o.Advertise = a
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultOptions returns router default options
|
||||
func DefaultOptions() Options {
|
||||
return Options{
|
||||
Id: uuid.New().String(),
|
||||
Address: DefaultAddress,
|
||||
Network: DefaultNetwork,
|
||||
Registry: registry.DefaultRegistry,
|
||||
Id: uuid.New().String(),
|
||||
Address: DefaultAddress,
|
||||
Network: DefaultNetwork,
|
||||
Registry: registry.DefaultRegistry,
|
||||
Advertise: AdvertiseBest,
|
||||
}
|
||||
}
|
||||
|
@ -139,6 +139,28 @@ type Advert struct {
|
||||
Events []*Event
|
||||
}
|
||||
|
||||
// Strategy is route advertisement strategy
|
||||
type Strategy int
|
||||
|
||||
const (
|
||||
// AdvertiseAll advertises all routes to the network
|
||||
AdvertiseAll Strategy = iota
|
||||
// AdvertiseBest advertises optimal routes to the network
|
||||
AdvertiseBest
|
||||
)
|
||||
|
||||
// String returns human readable Strategy
|
||||
func (s Strategy) String() string {
|
||||
switch s {
|
||||
case AdvertiseAll:
|
||||
return "all"
|
||||
case AdvertiseBest:
|
||||
return "best"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
// NewRouter creates new Router and returns it
|
||||
func NewRouter(opts ...Option) Router {
|
||||
return newRouter(opts...)
|
||||
|
Loading…
Reference in New Issue
Block a user