diff options
Diffstat (limited to 'server/bmp.go')
-rw-r--r-- | server/bmp.go | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/server/bmp.go b/server/bmp.go new file mode 100644 index 00000000..2a00b73d --- /dev/null +++ b/server/bmp.go @@ -0,0 +1,132 @@ +// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + log "github.com/Sirupsen/logrus" + "github.com/osrg/gobgp/config" + "github.com/osrg/gobgp/packet" + "github.com/osrg/gobgp/table" + "net" + "strconv" + "time" +) + +type broadcastBMPMsg struct { + ch chan *broadcastBMPMsg + msgList []*bgp.BMPMessage + conn *net.TCPConn + addr string +} + +func (m *broadcastBMPMsg) send() { + m.ch <- m +} + +type bmpConn struct { + conn *net.TCPConn + addr string +} + +type bmpClient struct { + ch chan *broadcastBMPMsg + connCh chan *bmpConn +} + +func newBMPClient(conf config.BmpServers, connCh chan *bmpConn) (*bmpClient, error) { + b := &bmpClient{} + if len(conf.BmpServerList) == 0 { + return b, nil + } + + b.ch = make(chan *broadcastBMPMsg) + b.connCh = connCh + + tryConnect := func(addr string) { + for { + conn, err := net.Dial("tcp", addr) + if err != nil { + time.Sleep(30 * time.Second) + } else { + log.Info("bmp server is connected, ", addr) + connCh <- &bmpConn{ + conn: conn.(*net.TCPConn), + addr: addr, + } + break + } + } + } + + for _, c := range conf.BmpServerList { + b := c.BmpServerConfig + go tryConnect(net.JoinHostPort(b.Address.String(), strconv.Itoa(int(b.Port)))) + } + + go func() { + connMap := make(map[string]*net.TCPConn) + for { + select { + case m := <-b.ch: + if m.conn != nil { + i := bgp.NewBMPInitiation([]bgp.BMPTLV{}) + buf, _ := i.Serialize() + _, err := m.conn.Write(buf) + if err == nil { + connMap[m.addr] = m.conn + } + } + + for addr, conn := range connMap { + if m.conn != nil && m.conn != conn { + continue + } + + for _, msg := range m.msgList { + b, _ := msg.Serialize() + _, err := conn.Write(b) + if err != nil { + delete(connMap, addr) + go tryConnect(addr) + break + } + } + } + } + } + }() + + return b, nil +} + +func (c *bmpClient) send() chan *broadcastBMPMsg { + return c.ch +} + +func bmpPeerUp(laddr string, lport, rport uint16, sent, recv *bgp.BGPMessage, t int, policy bool, pd uint64, peeri *table.PeerInfo, timestamp int64) *bgp.BMPMessage { + ph := bgp.NewBMPPeerHeader(uint8(t), policy, pd, peeri.Address.String(), peeri.AS, peeri.LocalID.String(), float64(timestamp)) + return bgp.NewBMPPeerUpNotification(*ph, laddr, lport, rport, sent, recv) +} + +func bmpPeerDown(reason uint8, t int, policy bool, pd uint64, peeri *table.PeerInfo, timestamp int64) *bgp.BMPMessage { + ph := bgp.NewBMPPeerHeader(uint8(t), policy, pd, peeri.Address.String(), peeri.AS, peeri.LocalID.String(), float64(timestamp)) + return bgp.NewBMPPeerDownNotification(*ph, reason, nil, []byte{}) +} + +func bmpPeerRoute(t int, policy bool, pd uint64, peeri *table.PeerInfo, timestamp int64, u *bgp.BGPMessage) *bgp.BMPMessage { + ph := bgp.NewBMPPeerHeader(uint8(t), policy, pd, peeri.Address.String(), peeri.AS, peeri.LocalID.String(), float64(timestamp)) + return bgp.NewBMPRouteMonitoring(*ph, u) +} |