summaryrefslogtreecommitdiffhomepage
path: root/pkg/server/server.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/server/server.go')
-rw-r--r--pkg/server/server.go83
1 files changed, 83 insertions, 0 deletions
diff --git a/pkg/server/server.go b/pkg/server/server.go
index d756b29c..49065400 100644
--- a/pkg/server/server.go
+++ b/pkg/server/server.go
@@ -3340,6 +3340,89 @@ func (s *BgpServer) ResetRpki(ctx context.Context, r *api.ResetRpkiRequest) erro
}, false)
}
+type TableMonitor struct {
+ Inbox chan *api.Path
+ done chan interface{}
+ w *watcher
+}
+
+func (tm *TableMonitor) Close() {
+ close(tm.done)
+}
+
+func (s *BgpServer) NewTableMonitor(r *api.MonitorTableRequest) (*TableMonitor, error) {
+ if r == nil {
+ return nil, fmt.Errorf("nil request")
+ }
+ w, err := func() (*watcher, error) {
+ switch r.Type {
+ case api.Resource_GLOBAL:
+ return s.watch(watchBestPath(r.Current)), nil
+ case api.Resource_ADJ_IN:
+ if r.PostPolicy {
+ return s.watch(watchPostUpdate(r.Current)), nil
+ }
+ return s.watch(watchUpdate(r.Current)), nil
+ default:
+ return nil, fmt.Errorf("unsupported resource type: %v", r.Type)
+ }
+ }()
+ if err != nil {
+ return nil, err
+ }
+
+ tm := &TableMonitor{
+ Inbox: make(chan *api.Path),
+ done: make(chan interface{}),
+ w: w,
+ }
+ go func() {
+ defer func() {
+ close(tm.Inbox)
+ tm.w.Stop()
+ }()
+ family := bgp.RouteFamily(0)
+ if r.Family != nil {
+ family = bgp.AfiSafiToRouteFamily(uint16(r.Family.Afi), uint8(r.Family.Safi))
+ }
+
+ for {
+ select {
+ case ev := <-tm.w.Event():
+ var pl []*table.Path
+ switch msg := ev.(type) {
+ case *watchEventBestPath:
+ if len(msg.MultiPathList) > 0 {
+ l := make([]*table.Path, 0)
+ for _, p := range msg.MultiPathList {
+ l = append(l, p...)
+ }
+ pl = l
+ } else {
+ pl = msg.PathList
+ }
+ case *watchEventUpdate:
+ pl = msg.PathList
+ }
+ for _, path := range pl {
+ if path == nil || (r.Family != nil && family != path.GetRouteFamily()) {
+ continue
+ }
+ select {
+ case tm.Inbox <- toPathApi(path, nil):
+ case <-tm.done:
+ return
+ }
+ }
+ case <-tm.done:
+ return
+ }
+ }
+ }()
+
+ return tm, nil
+}
+
type PeerMonitor struct {
Inbox chan *api.Peer
done chan interface{}