summaryrefslogtreecommitdiffhomepage
path: root/server/bmp.go
diff options
context:
space:
mode:
Diffstat (limited to 'server/bmp.go')
-rw-r--r--server/bmp.go358
1 files changed, 0 insertions, 358 deletions
diff --git a/server/bmp.go b/server/bmp.go
deleted file mode 100644
index 91507cd3..00000000
--- a/server/bmp.go
+++ /dev/null
@@ -1,358 +0,0 @@
-// Copyright (C) 2015-2016 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 (
- "fmt"
- "net"
- "strconv"
- "time"
-
- "github.com/osrg/gobgp/config"
- "github.com/osrg/gobgp/packet/bgp"
- "github.com/osrg/gobgp/packet/bmp"
- "github.com/osrg/gobgp/table"
- log "github.com/sirupsen/logrus"
-)
-
-type ribout map[string][]*table.Path
-
-func newribout() ribout {
- return make(map[string][]*table.Path)
-}
-
-// return true if we need to send the path to the BMP server
-func (r ribout) update(p *table.Path) bool {
- key := p.GetNlri().String() // TODO expose (*Path).getPrefix()
- l := r[key]
- if p.IsWithdraw {
- if len(l) == 0 {
- return false
- }
- n := make([]*table.Path, 0, len(l))
- for _, q := range l {
- if p.GetSource() == q.GetSource() {
- continue
- }
- n = append(n, q)
- }
- if len(n) == 0 {
- delete(r, key)
- } else {
- r[key] = n
- }
- return true
- }
-
- if len(l) == 0 {
- r[key] = []*table.Path{p}
- return true
- }
-
- doAppend := true
- for idx, q := range l {
- if p.GetSource() == q.GetSource() {
- // if we have sent the same path, don't send it again
- if p.Equal(q) {
- return false
- }
- l[idx] = p
- doAppend = false
- }
- }
- if doAppend {
- r[key] = append(r[key], p)
- }
- return true
-}
-
-func (b *bmpClient) tryConnect() *net.TCPConn {
- interval := 1
- for {
- log.WithFields(log.Fields{"Topic": "bmp"}).Debugf("Connecting BMP server:%s", b.host)
- conn, err := net.Dial("tcp", b.host)
- if err != nil {
- select {
- case <-b.dead:
- return nil
- default:
- }
- time.Sleep(time.Duration(interval) * time.Second)
- if interval < 30 {
- interval *= 2
- }
- } else {
- log.WithFields(log.Fields{"Topic": "bmp"}).Infof("BMP server is connected:%s", b.host)
- return conn.(*net.TCPConn)
- }
- }
-}
-
-func (b *bmpClient) Stop() {
- close(b.dead)
-}
-
-func (b *bmpClient) loop() {
- for {
- conn := b.tryConnect()
- if conn == nil {
- break
- }
-
- if func() bool {
- ops := []WatchOption{WatchPeerState(true)}
- if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_BOTH {
- log.WithFields(
- log.Fields{"Topic": "bmp"},
- ).Warn("both option for route-monitoring-policy is obsoleted")
- }
- if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL {
- ops = append(ops, WatchUpdate(true))
- }
- if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL {
- ops = append(ops, WatchPostUpdate(true))
- }
- if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_LOCAL_RIB || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL {
- ops = append(ops, WatchBestPath(true))
- }
- if b.c.RouteMirroringEnabled {
- ops = append(ops, WatchMessage(false))
- }
- w := b.s.Watch(ops...)
- defer w.Stop()
-
- var tickerCh <-chan time.Time
- if b.c.StatisticsTimeout == 0 {
- log.WithFields(log.Fields{"Topic": "bmp"}).Debug("statistics reports disabled")
- } else {
- t := time.NewTicker(time.Duration(b.c.StatisticsTimeout) * time.Second)
- defer t.Stop()
- tickerCh = t.C
- }
-
- 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.BMPInfoTLVInterface{})); 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 msg.Payload == nil {
- var pathList []*table.Path
- if msg.Init {
- pathList = msg.PathList
- } else {
- for _, p := range msg.PathList {
- if b.ribout.update(p) {
- pathList = append(pathList, p)
- }
- }
- }
- for _, path := range pathList {
- for _, u := range table.CreateUpdateMsgFromPaths([]*table.Path{path}) {
- payload, _ := u.Serialize()
- if err := write(bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.PostPolicy, 0, true, info, msg.Timestamp.Unix(), payload)); err != nil {
- return false
- }
- }
- }
- } else {
- if err := write(bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.PostPolicy, 0, msg.FourBytesAs, info, msg.Timestamp.Unix(), msg.Payload)); err != nil {
- return false
- }
- }
- case *WatchEventBestPath:
- info := &table.PeerInfo{
- Address: net.ParseIP("0.0.0.0").To4(),
- AS: b.s.bgpConfig.Global.Config.As,
- ID: net.ParseIP(b.s.bgpConfig.Global.Config.RouterId).To4(),
- }
- for _, p := range msg.PathList {
- u := table.CreateUpdateMsgFromPaths([]*table.Path{p})[0]
- if payload, err := u.Serialize(); err != nil {
- return false
- } else if err = write(bmpPeerRoute(bmp.BMP_PEER_TYPE_LOCAL_RIB, false, 0, true, info, p.GetTimestamp().Unix(), payload)); err != nil {
- return false
- }
- }
- case *WatchEventPeerState:
- if msg.State == bgp.BGP_FSM_ESTABLISHED {
- if err := write(bmpPeerUp(msg, bmp.BMP_PEER_TYPE_GLOBAL, false, 0)); err != nil {
- return false
- }
- } else {
- if err := write(bmpPeerDown(msg, bmp.BMP_PEER_TYPE_GLOBAL, false, 0)); err != nil {
- return false
- }
- }
- case *WatchEventMessage:
- info := &table.PeerInfo{
- Address: msg.PeerAddress,
- AS: msg.PeerAS,
- ID: msg.PeerID,
- }
- if err := write(bmpPeerRouteMirroring(bmp.BMP_PEER_TYPE_GLOBAL, 0, info, msg.Timestamp.Unix(), msg.Message)); err != nil {
- return false
- }
- }
- case <-tickerCh:
- neighborList := b.s.GetNeighbor("", true)
- for _, n := range neighborList {
- if n.State.SessionState != config.SESSION_STATE_ESTABLISHED {
- continue
- }
- if err := write(bmpPeerStats(bmp.BMP_PEER_TYPE_GLOBAL, 0, 0, n)); err != nil {
- return false
- }
- }
- case <-b.dead:
- term := bmp.NewBMPTermination([]bmp.BMPTermTLVInterface{
- bmp.NewBMPTermTLV16(bmp.BMP_TERM_TLV_TYPE_REASON, bmp.BMP_TERM_REASON_PERMANENTLY_ADMIN),
- })
- if err := write(term); err != nil {
- return false
- }
- conn.Close()
- return true
- }
- }
- }() {
- return
- }
- }
-}
-
-type bmpClient struct {
- s *BgpServer
- dead chan struct{}
- host string
- c *config.BmpServerConfig
- ribout ribout
-}
-
-func bmpPeerUp(ev *WatchEventPeerState, t uint8, policy bool, pd uint64) *bmp.BMPMessage {
- var flags uint8 = 0
- if policy {
- flags |= bmp.BMP_PEER_FLAG_POST_POLICY
- }
- ph := bmp.NewBMPPeerHeader(t, flags, pd, ev.PeerAddress.String(), ev.PeerAS, ev.PeerID.String(), float64(ev.Timestamp.Unix()))
- return bmp.NewBMPPeerUpNotification(*ph, ev.LocalAddress.String(), ev.LocalPort, ev.PeerPort, ev.SentOpen, ev.RecvOpen)
-}
-
-func bmpPeerDown(ev *WatchEventPeerState, t uint8, policy bool, pd uint64) *bmp.BMPMessage {
- var flags uint8 = 0
- if policy {
- flags |= bmp.BMP_PEER_FLAG_POST_POLICY
- }
- ph := bmp.NewBMPPeerHeader(t, flags, pd, ev.PeerAddress.String(), ev.PeerAS, ev.PeerID.String(), float64(ev.Timestamp.Unix()))
- return bmp.NewBMPPeerDownNotification(*ph, uint8(ev.StateReason.PeerDownReason), ev.StateReason.BGPNotification, ev.StateReason.Data)
-}
-
-func bmpPeerRoute(t uint8, policy bool, pd uint64, fourBytesAs bool, peeri *table.PeerInfo, timestamp int64, payload []byte) *bmp.BMPMessage {
- var flags uint8 = 0
- if policy {
- flags |= bmp.BMP_PEER_FLAG_POST_POLICY
- }
- if !fourBytesAs {
- flags |= bmp.BMP_PEER_FLAG_TWO_AS
- }
- ph := bmp.NewBMPPeerHeader(t, flags, pd, peeri.Address.String(), peeri.AS, peeri.ID.String(), float64(timestamp))
- m := bmp.NewBMPRouteMonitoring(*ph, nil)
- body := m.Body.(*bmp.BMPRouteMonitoring)
- body.BGPUpdatePayload = payload
- return m
-}
-
-func bmpPeerStats(peerType uint8, peerDist uint64, timestamp int64, neighConf *config.Neighbor) *bmp.BMPMessage {
- var peerFlags uint8 = 0
- ph := bmp.NewBMPPeerHeader(peerType, peerFlags, peerDist, neighConf.State.NeighborAddress, neighConf.State.PeerAs, neighConf.State.RemoteRouterId, float64(timestamp))
- return bmp.NewBMPStatisticsReport(
- *ph,
- []bmp.BMPStatsTLVInterface{
- bmp.NewBMPStatsTLV64(bmp.BMP_STAT_TYPE_ADJ_RIB_IN, uint64(neighConf.State.AdjTable.Accepted)),
- bmp.NewBMPStatsTLV64(bmp.BMP_STAT_TYPE_LOC_RIB, uint64(neighConf.State.AdjTable.Advertised+neighConf.State.AdjTable.Filtered)),
- bmp.NewBMPStatsTLV32(bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE, neighConf.State.Messages.Received.WithdrawUpdate),
- bmp.NewBMPStatsTLV32(bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX, neighConf.State.Messages.Received.WithdrawPrefix),
- },
- )
-}
-
-func bmpPeerRouteMirroring(peerType uint8, peerDist uint64, peerInfo *table.PeerInfo, timestamp int64, msg *bgp.BGPMessage) *bmp.BMPMessage {
- var peerFlags uint8 = 0
- ph := bmp.NewBMPPeerHeader(peerType, peerFlags, peerDist, peerInfo.Address.String(), peerInfo.AS, peerInfo.ID.String(), float64(timestamp))
- return bmp.NewBMPRouteMirroring(
- *ph,
- []bmp.BMPRouteMirrTLVInterface{
- // RFC7854: BGP Message TLV MUST occur last in the list of TLVs
- bmp.NewBMPRouteMirrTLVBGPMsg(bmp.BMP_ROUTE_MIRRORING_TLV_TYPE_BGP_MSG, msg),
- },
- )
-}
-
-func (b *bmpClientManager) addServer(c *config.BmpServerConfig) error {
- host := net.JoinHostPort(c.Address, strconv.Itoa(int(c.Port)))
- if _, y := b.clientMap[host]; y {
- return fmt.Errorf("bmp client %s is already configured", host)
- }
- b.clientMap[host] = &bmpClient{
- s: b.s,
- dead: make(chan struct{}),
- host: host,
- c: c,
- ribout: newribout(),
- }
- go b.clientMap[host].loop()
- return nil
-}
-
-func (b *bmpClientManager) deleteServer(c *config.BmpServerConfig) error {
- host := net.JoinHostPort(c.Address, strconv.Itoa(int(c.Port)))
- if c, y := b.clientMap[host]; !y {
- return fmt.Errorf("bmp client %s isn't found", host)
- } else {
- c.Stop()
- delete(b.clientMap, host)
- }
- return nil
-}
-
-type bmpClientManager struct {
- s *BgpServer
- clientMap map[string]*bmpClient
-}
-
-func newBmpClientManager(s *BgpServer) *bmpClientManager {
- return &bmpClientManager{
- s: s,
- clientMap: make(map[string]*bmpClient),
- }
-}