func (w *bmpWatcher) loop() error { for { select { case <-w.t.Dying(): for _, server := range w.connMap { if server.conn != nil { server.conn.Close() } } return nil case m := <-w.ctlCh: c := m.config if m.del { host := net.JoinHostPort(c.Address, strconv.Itoa(int(c.Port))) if _, y := w.connMap[host]; !y { m.errCh <- fmt.Errorf("bmp server %s doesn't exists", host) continue } conn := w.connMap[host].conn delete(w.connMap, host) conn.Close() } else { host := net.JoinHostPort(c.Address, strconv.Itoa(int(c.Port))) if _, y := w.connMap[host]; y { m.errCh <- fmt.Errorf("bmp server %s already exists", host) continue } server := &bmpServer{ host: host, typ: c.RouteMonitoringPolicy, } w.connMap[host] = server go w.tryConnect(server) } m.errCh <- nil close(m.errCh) case newConn := <-w.newConnCh: server, y := w.connMap[newConn.RemoteAddr().String()] if !y { log.Warnf("Can't find bmp server %s", newConn.RemoteAddr().String()) break } i := bmp.NewBMPInitiation([]bmp.BMPTLV{}) buf, _ := i.Serialize() if _, err := newConn.Write(buf); err != nil { log.Warnf("failed to write to bmp server %s", server.host) go w.tryConnect(server) break } req := &GrpcRequest{ RequestType: REQ_BMP_NEIGHBORS, ResponseCh: make(chan *GrpcResponse, 1), } w.apiCh <- req write := func(req *GrpcRequest) error { for res := range req.ResponseCh { for _, msg := range res.Data.([]*bmp.BMPMessage) { buf, _ = msg.Serialize() if _, err := newConn.Write(buf); err != nil { log.Warnf("failed to write to bmp server %s %s", server.host, err) go w.tryConnect(server) return err } } } return nil } if err := write(req); err != nil { break } if server.typ != config.BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY { req = &GrpcRequest{ RequestType: REQ_BMP_ADJ_IN, ResponseCh: make(chan *GrpcResponse, 1), } w.apiCh <- req if err := write(req); err != nil { break } } if server.typ != config.BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY { req = &GrpcRequest{ RequestType: REQ_BMP_GLOBAL, ResponseCh: make(chan *GrpcResponse, 1), } w.apiCh <- req if err := write(req); err != nil { break } } server.conn = newConn case ev := <-w.ch: switch msg := ev.(type) { case *watcherEventUpdateMsg: info := &table.PeerInfo{ Address: msg.peerAddress, AS: msg.peerAS, ID: msg.peerID, } buf, _ := bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.postPolicy, 0, info, msg.timestamp.Unix(), msg.payload).Serialize() for _, server := range w.connMap { if server.conn != nil { send := server.typ != config.BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY && !msg.postPolicy send = send || (server.typ != config.BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY && msg.postPolicy) if send { _, err := server.conn.Write(buf) if err != nil { log.Warnf("failed to write to bmp server %s", server.host) } } } } case *watcherEventStateChangedMsg: var bmpmsg *bmp.BMPMessage info := &table.PeerInfo{ Address: msg.peerAddress, AS: msg.peerAS, ID: msg.peerID, } if msg.state == bgp.BGP_FSM_ESTABLISHED { bmpmsg = bmpPeerUp(msg.localAddress.String(), msg.localPort, msg.peerPort, msg.sentOpen, msg.recvOpen, bmp.BMP_PEER_TYPE_GLOBAL, false, 0, info, msg.timestamp.Unix()) } else { bmpmsg = bmpPeerDown(bmp.BMP_PEER_DOWN_REASON_UNKNOWN, bmp.BMP_PEER_TYPE_GLOBAL, false, 0, info, msg.timestamp.Unix()) } buf, _ := bmpmsg.Serialize() for _, server := range w.connMap { if server.conn != nil { _, err := server.conn.Write(buf) if err != nil { log.Warnf("failed to write to bmp server %s", server.host) } } } default: log.Warnf("unknown watcher event") } case conn := <-w.endCh: host := conn.RemoteAddr().String() log.Debugf("bmp connection to %s killed", host) if _, y := w.connMap[host]; y { w.connMap[host].conn = nil go w.tryConnect(w.connMap[host]) } } } }
func (b *bmpClient) loop() { for { conn := b.tryConnect() if conn == nil { break } if func() bool { ops := []WatchOption{WatchPeerState(true)} if b.typ != config.BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY { ops = append(ops, WatchUpdate(true)) } else if b.typ != config.BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY { ops = append(ops, WatchPostUpdate(true)) } w := b.s.Watch(ops...) defer w.Stop() write := func(msg *bmp.BMPMessage) error { buf, _ := msg.Serialize() _, err := conn.Write(buf) if err != nil { log.Warnf("failed to write to bmp server %s", b.host) } return err } if err := write(bmp.NewBMPInitiation([]bmp.BMPTLV{})); err != nil { return false } for { select { case ev := <-w.Event(): switch msg := ev.(type) { case *WatchEventUpdate: info := &table.PeerInfo{ Address: msg.PeerAddress, AS: msg.PeerAS, ID: msg.PeerID, } if err := write(bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.PostPolicy, 0, info, msg.Timestamp.Unix(), msg.Payload)); err != nil { return false } case *WatchEventPeerState: info := &table.PeerInfo{ Address: msg.PeerAddress, AS: msg.PeerAS, ID: msg.PeerID, } if msg.State == bgp.BGP_FSM_ESTABLISHED { if err := write(bmpPeerUp(msg.LocalAddress.String(), msg.LocalPort, msg.PeerPort, msg.SentOpen, msg.RecvOpen, bmp.BMP_PEER_TYPE_GLOBAL, false, 0, info, msg.Timestamp.Unix())); err != nil { return false } } else { if err := write(bmpPeerDown(bmp.BMP_PEER_DOWN_REASON_UNKNOWN, bmp.BMP_PEER_TYPE_GLOBAL, false, 0, info, msg.Timestamp.Unix())); err != nil { return false } } } case <-b.dead: conn.Close() return true } } }() { return } } }