summaryrefslogtreecommitdiffhomepage
path: root/server/bmp.go
diff options
context:
space:
mode:
Diffstat (limited to 'server/bmp.go')
-rw-r--r--server/bmp.go132
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)
+}