mirror of
https://github.com/osrg/gobgp.git
synced 2024-05-11 05:55:10 +00:00
180 lines
4.6 KiB
Go
180 lines
4.6 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
|
|
}
|
|
|
|
func (m *broadcastBMPMsg) send() {
|
|
m.ch <- m
|
|
}
|
|
|
|
type bmpConn struct {
|
|
conn *net.TCPConn
|
|
host 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
|
|
|
|
endCh := make(chan *net.TCPConn)
|
|
|
|
tryConnect := func(host string) {
|
|
interval := 1
|
|
for {
|
|
log.Debug("connecting bmp server: ", host)
|
|
conn, err := net.Dial("tcp", host)
|
|
if err != nil {
|
|
time.Sleep(time.Duration(interval) * time.Second)
|
|
if interval < 30 {
|
|
interval *= 2
|
|
}
|
|
} else {
|
|
log.Info("bmp server is connected, ", host)
|
|
go func() {
|
|
buf := make([]byte, 1)
|
|
for {
|
|
_, err := conn.Read(buf)
|
|
if err != nil {
|
|
endCh <- conn.(*net.TCPConn)
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
connCh <- &bmpConn{
|
|
conn: conn.(*net.TCPConn),
|
|
host: host,
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, c := range conf.BmpServerList {
|
|
b := c.Config
|
|
go tryConnect(net.JoinHostPort(b.Address, 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.conn.RemoteAddr().String()] = m.conn
|
|
}
|
|
}
|
|
|
|
for host, conn := range connMap {
|
|
if m.conn != nil && m.conn != conn {
|
|
continue
|
|
}
|
|
|
|
for _, msg := range m.msgList {
|
|
if msg.Header.Type == bgp.BMP_MSG_ROUTE_MONITORING {
|
|
c := func() *config.BmpServerConfig {
|
|
for _, c := range conf.BmpServerList {
|
|
b := &c.Config
|
|
if host == net.JoinHostPort(b.Address, strconv.Itoa(int(b.Port))) {
|
|
return b
|
|
}
|
|
}
|
|
return nil
|
|
}()
|
|
if c == nil {
|
|
log.Fatal(host)
|
|
}
|
|
ph := msg.PeerHeader
|
|
switch c.RouteMonitoringPolicy {
|
|
case config.BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY:
|
|
if ph.IsPostPolicy != false {
|
|
continue
|
|
}
|
|
case config.BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY:
|
|
if ph.IsPostPolicy != true {
|
|
continue
|
|
}
|
|
}
|
|
|
|
}
|
|
b, _ := msg.Serialize()
|
|
if _, err := conn.Write(b); err != nil {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
case conn := <-endCh:
|
|
host := conn.RemoteAddr().String()
|
|
log.Debugf("bmp connection to %s killed", host)
|
|
delete(connMap, host)
|
|
go tryConnect(host)
|
|
}
|
|
}
|
|
}()
|
|
|
|
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, payload []byte) *bgp.BMPMessage {
|
|
ph := bgp.NewBMPPeerHeader(uint8(t), policy, pd, peeri.Address.String(), peeri.AS, peeri.LocalID.String(), float64(timestamp))
|
|
m := bgp.NewBMPRouteMonitoring(*ph, nil)
|
|
body := m.Body.(*bgp.BMPRouteMonitoring)
|
|
body.BGPUpdatePayload = payload
|
|
return m
|
|
}
|