Files
osrg-gobgp/server/bmp.go
T
FUJITA Tomonori 5be31cce0d Add bmp support
Can be enabled like:

[Global]
  [Global.GlobalConfig]
    As = 64512
    RouterId = "10.0.255.254"

[BmpServers]
  [[BmpServers.BmpServerList]]
    [BmpServers.BmpServerList.BmpServerConfig]
      Address = "127.0.0.1"
      Port=11019

Signed-off-by: FUJITA Tomonori <[email protected]>
2015-09-13 22:39:21 +09:00

133 lines
3.4 KiB
Go

// 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)
}