summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--api/grpc_server.go2
-rw-r--r--server/server.go12
-rw-r--r--server/server_test.go2
-rw-r--r--server/zclient.go2
-rw-r--r--table/destination.go18
-rw-r--r--table/table.go11
-rw-r--r--table/table_manager.go53
7 files changed, 77 insertions, 23 deletions
diff --git a/api/grpc_server.go b/api/grpc_server.go
index 8f75c1c1..8fbe53a2 100644
--- a/api/grpc_server.go
+++ b/api/grpc_server.go
@@ -347,7 +347,7 @@ func (s *Server) MonitorRib(arg *Table, stream GobgpApi_MonitorRibServer) error
w, err := func() (*server.Watcher, error) {
switch arg.Type {
case Resource_GLOBAL:
- return s.bgpServer.Watch(server.WatchBestPath()), nil
+ return s.bgpServer.Watch(server.WatchBestPath(false)), nil
case Resource_ADJ_IN:
if arg.PostPolicy {
return s.bgpServer.Watch(server.WatchPostUpdate(false)), nil
diff --git a/server/server.go b/server/server.go
index 435c9f72..ba30f578 100644
--- a/server/server.go
+++ b/server/server.go
@@ -2133,6 +2133,7 @@ type watchOptions struct {
preUpdate bool
postUpdate bool
peerState bool
+ initBest bool
initUpdate bool
initPostUpdate bool
initPeerState bool
@@ -2141,9 +2142,12 @@ type watchOptions struct {
type WatchOption func(*watchOptions)
-func WatchBestPath() WatchOption {
+func WatchBestPath(current bool) WatchOption {
return func(o *watchOptions) {
o.bestpath = true
+ if current {
+ o.initBest = true
+ }
}
}
@@ -2319,6 +2323,12 @@ func (s *BgpServer) Watch(opts ...WatchOption) (w *Watcher) {
w.notify(createWatchEventPeerState(peer))
}
}
+ if w.opts.initBest {
+ w.notify(&WatchEventBestPath{
+ PathList: s.globalRib.GetBestPathList(table.GLOBAL_RIB_NAME, nil),
+ MultiPathList: s.globalRib.GetBestMultiPathList(table.GLOBAL_RIB_NAME, nil),
+ })
+ }
if w.opts.initUpdate {
for _, peer := range s.neighborMap {
if peer.fsm.state != bgp.BGP_FSM_ESTABLISHED {
diff --git a/server/server_test.go b/server/server_test.go
index 73eadb0a..5e0dc5e0 100644
--- a/server/server_test.go
+++ b/server/server_test.go
@@ -113,7 +113,7 @@ func TestMonitor(test *testing.T) {
}
}
- w := s.Watch(WatchBestPath())
+ w := s.Watch(WatchBestPath(false))
attrs := []bgp.PathAttributeInterface{
bgp.NewPathAttributeOrigin(0),
diff --git a/server/zclient.go b/server/zclient.go
index df92f038..5f81cfcf 100644
--- a/server/zclient.go
+++ b/server/zclient.go
@@ -177,7 +177,7 @@ func (z *zebraClient) stop() {
}
func (z *zebraClient) loop() {
- w := z.server.Watch(WatchBestPath())
+ w := z.server.Watch(WatchBestPath(true))
defer func() { w.Stop() }()
for {
diff --git a/table/destination.go b/table/destination.go
index ac3ef0c8..1ded7962 100644
--- a/table/destination.go
+++ b/table/destination.go
@@ -182,6 +182,24 @@ func (dd *Destination) GetBestPath(id string) *Path {
return nil
}
+func (dd *Destination) GetMultiBestPath(id string) []*Path {
+ list := make([]*Path, 0, len(dd.knownPathList))
+ var best *Path
+ for _, p := range dd.knownPathList {
+ if p.Filtered(id) == POLICY_DIRECTION_NONE {
+ if best == nil {
+ best = p
+ list = append(list, p)
+ } else if best.Compare(p) == 0 {
+ list = append(list, p)
+ } else {
+ return list
+ }
+ }
+ }
+ return nil
+}
+
func (dd *Destination) AddWithdraw(withdraw *Path) {
dd.validatePath(withdraw)
dd.withdrawList = append(dd.withdrawList, withdraw)
diff --git a/table/table.go b/table/table.go
index 08637522..c3b48812 100644
--- a/table/table.go
+++ b/table/table.go
@@ -303,6 +303,17 @@ func (t *Table) Bests(id string) []*Path {
return paths
}
+func (t *Table) MultiBests(id string) [][]*Path {
+ paths := make([][]*Path, 0, len(t.destinations))
+ for _, dst := range t.destinations {
+ path := dst.GetMultiBestPath(id)
+ if path != nil {
+ paths = append(paths, path)
+ }
+ }
+ return paths
+}
+
func (t *Table) GetKnownPathList(id string) []*Path {
paths := make([]*Path, 0, len(t.destinations))
for _, dst := range t.destinations {
diff --git a/table/table_manager.go b/table/table_manager.go
index ae00d3ce..15caa924 100644
--- a/table/table_manager.go
+++ b/table/table_manager.go
@@ -299,38 +299,53 @@ func (manager *TableManager) handleMacMobility(path *Path) []*Destination {
return dsts
}
+func (manager *TableManager) tables(list ...bgp.RouteFamily) []*Table {
+ l := make([]*Table, 0, len(manager.Tables))
+ if len(list) == 0 {
+ for _, v := range manager.Tables {
+ l = append(l, v)
+ }
+ return l
+ }
+ for _, f := range list {
+ if t, ok := manager.Tables[f]; ok {
+ l = append(l, t)
+ }
+ }
+ return l
+}
+
func (manager *TableManager) getDestinationCount(rfList []bgp.RouteFamily) int {
count := 0
- for _, rf := range rfList {
- if _, ok := manager.Tables[rf]; ok {
- count += len(manager.Tables[rf].GetDestinations())
- }
+ for _, t := range manager.tables(rfList...) {
+ count += len(t.GetDestinations())
}
return count
}
func (manager *TableManager) GetBestPathList(id string, rfList []bgp.RouteFamily) []*Path {
paths := make([]*Path, 0, manager.getDestinationCount(rfList))
- for _, rf := range rfList {
- if t, ok := manager.Tables[rf]; ok {
- paths = append(paths, t.Bests(id)...)
- }
+ for _, t := range manager.tables(rfList...) {
+ paths = append(paths, t.Bests(id)...)
}
return paths
}
-func (manager *TableManager) GetPathList(id string, rfList []bgp.RouteFamily) []*Path {
- c := 0
- for _, rf := range rfList {
- if t, ok := manager.Tables[rf]; ok {
- c += len(t.destinations)
- }
+func (manager *TableManager) GetBestMultiPathList(id string, rfList []bgp.RouteFamily) [][]*Path {
+ if !UseMultiplePaths.Enabled {
+ return nil
}
- paths := make([]*Path, 0, c)
- for _, rf := range rfList {
- if t, ok := manager.Tables[rf]; ok {
- paths = append(paths, t.GetKnownPathList(id)...)
- }
+ paths := make([][]*Path, 0, manager.getDestinationCount(rfList))
+ for _, t := range manager.tables(rfList...) {
+ paths = append(paths, t.MultiBests(id)...)
+ }
+ return paths
+}
+
+func (manager *TableManager) GetPathList(id string, rfList []bgp.RouteFamily) []*Path {
+ paths := make([]*Path, 0, manager.getDestinationCount(rfList))
+ for _, t := range manager.tables(rfList...) {
+ paths = append(paths, t.GetKnownPathList(id)...)
}
return paths
}