diff options
-rw-r--r-- | gobgpd/main.go | 6 | ||||
-rw-r--r-- | server/server.go | 47 | ||||
-rw-r--r-- | server/zclient.go | 50 |
3 files changed, 43 insertions, 60 deletions
diff --git a/gobgpd/main.go b/gobgpd/main.go index 67a0b2f4..060ef038 100644 --- a/gobgpd/main.go +++ b/gobgpd/main.go @@ -209,8 +209,10 @@ func main() { if err := bgpServer.SetGlobalType(newConfig.Global); err != nil { log.Fatalf("failed to set global config: %s", err) } - if err := bgpServer.SetZebraConfig(newConfig.Zebra); err != nil { - log.Fatalf("failed to set zebra config: %s", err) + if newConfig.Zebra.Config.Enabled { + if err := bgpServer.StartZebraClient(&newConfig.Zebra); err != nil { + log.Fatalf("failed to set zebra config: %s", err) + } } if err := bgpServer.SetCollector(newConfig.Collector); err != nil { log.Fatalf("failed to set collector config: %s", err) diff --git a/server/server.go b/server/server.go index e6d78112..4cd71ad6 100644 --- a/server/server.go +++ b/server/server.go @@ -106,6 +106,7 @@ type BgpServer struct { shutdown bool watchers *watcherManager watcherMap map[watchType][]*Watcher + zclient *zebraClient } func NewBgpServer() *BgpServer { @@ -840,20 +841,26 @@ func (server *BgpServer) SetCollector(c config.Collector) error { return nil } -func (server *BgpServer) SetZebraConfig(z config.Zebra) error { - if !z.Config.Enabled { - return nil - } - ch := make(chan *GrpcResponse) - server.GrpcReqCh <- &GrpcRequest{ - RequestType: REQ_INITIALIZE_ZEBRA, - Data: &z.Config, - ResponseCh: ch, - } - if err := (<-ch).Err(); err != nil { - return err +func (s *BgpServer) StartZebraClient(x *config.Zebra) (err error) { + ch := make(chan struct{}) + defer func() { <-ch }() + + s.mgmtCh <- func() { + defer close(ch) + + if s.zclient != nil { + err = fmt.Errorf("already connected to Zebra") + } else { + c := x.Config + + protos := make([]string, 0, len(c.RedistributeRouteTypeList)) + for _, p := range c.RedistributeRouteTypeList { + protos = append(protos, string(p)) + } + s.zclient, err = newZebraClient(s, c.Url, protos) + } } - return nil + return err } func (server *BgpServer) SetRpkiConfig(c []config.RpkiServer) error { @@ -1819,20 +1826,6 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) { if len(pathList) > 0 { server.propagateUpdate(nil, pathList) } - case REQ_INITIALIZE_ZEBRA: - c := grpcReq.Data.(*config.ZebraConfig) - protos := make([]string, 0, len(c.RedistributeRouteTypeList)) - for _, p := range c.RedistributeRouteTypeList { - protos = append(protos, string(p)) - } - z, err := newZebraWatcher(server, c.Url, protos) - if err == nil { - server.watchers.addWatcher(WATCHER_ZEBRA, z) - } - grpcReq.ResponseCh <- &GrpcResponse{ - ResponseErr: err, - } - close(grpcReq.ResponseCh) case REQ_INITIALIZE_COLLECTOR: c := grpcReq.Data.(*config.CollectorConfig) collector, err := NewCollector(server.GrpcReqCh, c.Url, c.DbName, c.TableDumpInterval) diff --git a/server/zclient.go b/server/zclient.go index 9a6885a3..23b74963 100644 --- a/server/zclient.go +++ b/server/zclient.go @@ -21,7 +21,6 @@ import ( "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" "github.com/osrg/gobgp/zebra" - "gopkg.in/tomb.v2" "net" "strconv" "strings" @@ -149,64 +148,53 @@ func createPathFromIPRouteMessage(m *zebra.Message) *table.Path { return path } -type zebraWatcher struct { - t tomb.Tomb - ch chan watcherEvent +type zebraClient struct { client *zebra.Client server *BgpServer + dead chan struct{} } -func (w *zebraWatcher) notify(t watcherEventType) chan watcherEvent { - if t == WATCHER_EVENT_BESTPATH_CHANGE { - return w.ch - } - return nil -} - -func (w *zebraWatcher) stop() { - w.t.Kill(nil) +func (z *zebraClient) stop() { + close(z.dead) } -func (w *zebraWatcher) watchingEventTypes() []watcherEventType { - return []watcherEventType{WATCHER_EVENT_BESTPATH_CHANGE} -} +func (z *zebraClient) loop() { + w := z.server.Watch(WatchBestPath()) + defer func() { w.Stop() }() -func (w *zebraWatcher) loop() error { for { select { - case <-w.t.Dying(): - return w.client.Close() - case msg := <-w.client.Receive(): + case <-z.dead: + return + case msg := <-z.client.Receive(): switch msg.Body.(type) { case *zebra.IPRouteBody: - p := createPathFromIPRouteMessage(msg) - if p != nil { - if _, err := w.server.AddPath("", []*table.Path{p}); err != nil { + if p := createPathFromIPRouteMessage(msg); p != nil { + if _, err := z.server.AddPath("", []*table.Path{p}); err != nil { log.Errorf("failed to add path from zebra: %s", p) } } } - case ev := <-w.ch: + case ev := <-w.Event(): msg := ev.(*watcherEventBestPathMsg) if table.UseMultiplePaths.Enabled { for _, dst := range msg.multiPathList { if m := newIPRouteMessage(dst); m != nil { - w.client.Send(m) + z.client.Send(m) } } } else { for _, path := range msg.pathList { if m := newIPRouteMessage([]*table.Path{path}); m != nil { - w.client.Send(m) + z.client.Send(m) } } } } } - return nil } -func newZebraWatcher(s *BgpServer, url string, protos []string) (*zebraWatcher, error) { +func newZebraClient(s *BgpServer, url string, protos []string) (*zebraClient, error) { l := strings.SplitN(url, ":", 2) if len(l) != 2 { return nil, fmt.Errorf("unsupported url: %s", url) @@ -225,11 +213,11 @@ func newZebraWatcher(s *BgpServer, url string, protos []string) (*zebraWatcher, } cli.SendRedistribute(t) } - w := &zebraWatcher{ - ch: make(chan watcherEvent), + w := &zebraClient{ + dead: make(chan struct{}), client: cli, server: s, } - w.t.Go(w.loop) + go w.loop() return w, nil } |