summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorWataru Ishida <ishida.wataru@lab.ntt.co.jp>2016-12-08 03:14:08 -0500
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-12-19 08:50:09 +0900
commit393b7232e76e0521079bc54f0cccbc1492c42d58 (patch)
treedab1f87f7331076b69ce4aacaa040555982b0285
parent6dcb1e4ae0f7e323a117b5cd22f014a599a24fc1 (diff)
bmp: don't send paths already sent in case of softresetin happens
Signed-off-by: Wataru Ishida <ishida.wataru@lab.ntt.co.jp>
-rw-r--r--server/bmp.go88
-rw-r--r--server/server.go6
2 files changed, 79 insertions, 15 deletions
diff --git a/server/bmp.go b/server/bmp.go
index 3522da98..154175c5 100644
--- a/server/bmp.go
+++ b/server/bmp.go
@@ -27,6 +27,57 @@ import (
"time"
)
+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 {
@@ -93,8 +144,23 @@ func (b *bmpClient) loop() {
AS: msg.PeerAS,
ID: msg.PeerID,
}
- if err := write(bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.PostPolicy, 0, info, msg.Timestamp.Unix(), msg.Payload)); err != nil {
- return false
+ if msg.Payload == nil {
+ pathList := make([]*table.Path, 0, len(msg.PathList))
+ for _, p := range msg.PathList {
+ if b.ribout.update(p) {
+ pathList = append(pathList, p)
+ }
+ }
+ for _, u := range table.CreateUpdateMsgFromPaths(pathList) {
+ payload, _ := u.Serialize()
+ if err := write(bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.PostPolicy, 0, info, msg.Timestamp.Unix(), payload)); err != nil {
+ return false
+ }
+ }
+ } else {
+ if err := write(bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.PostPolicy, 0, info, msg.Timestamp.Unix(), msg.Payload)); err != nil {
+ return false
+ }
}
case *WatchEventPeerState:
info := &table.PeerInfo{
@@ -124,10 +190,11 @@ func (b *bmpClient) loop() {
}
type bmpClient struct {
- s *BgpServer
- dead chan struct{}
- host string
- typ config.BmpRouteMonitoringPolicyType
+ s *BgpServer
+ dead chan struct{}
+ host string
+ typ config.BmpRouteMonitoringPolicyType
+ ribout ribout
}
func bmpPeerUp(laddr string, lport, rport uint16, sent, recv *bgp.BGPMessage, t uint8, policy bool, pd uint64, peeri *table.PeerInfo, timestamp int64) *bmp.BMPMessage {
@@ -154,10 +221,11 @@ func (b *bmpClientManager) addServer(c *config.BmpServerConfig) error {
return fmt.Errorf("bmp client %s is already configured", host)
}
b.clientMap[host] = &bmpClient{
- s: b.s,
- dead: make(chan struct{}),
- host: host,
- typ: c.RouteMonitoringPolicy,
+ s: b.s,
+ dead: make(chan struct{}),
+ host: host,
+ typ: c.RouteMonitoringPolicy,
+ ribout: newribout(),
}
go b.clientMap[host].loop()
return nil
diff --git a/server/server.go b/server/server.go
index b5fce0db..2ab17a4e 100644
--- a/server/server.go
+++ b/server/server.go
@@ -442,11 +442,7 @@ func (server *BgpServer) notifyPostPolicyUpdateWatcher(peer *Peer, pathList []*t
PostPolicy: true,
PathList: cloned,
}
- for _, u := range table.CreateUpdateMsgFromPaths(cloned) {
- payload, _ := u.Serialize()
- ev.Payload = payload
- server.notifyWatcher(WATCH_EVENT_TYPE_POST_UPDATE, ev)
- }
+ server.notifyWatcher(WATCH_EVENT_TYPE_POST_UPDATE, ev)
}
func (server *BgpServer) dropPeerAllRoutes(peer *Peer, families []bgp.RouteFamily) {