diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2016-02-10 23:41:44 -0800 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-02-10 23:41:44 -0800 |
commit | 023a498e4a90982095c870c5491770bf4952fc2b (patch) | |
tree | 135c11a05d8ff106264d91f0965aa6d926ac861b /server/server.go | |
parent | b19bbd415e8d33f01bcd407baece94ea1b81c957 (diff) |
server: support graceful-restart helper-speaker behavior
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
Diffstat (limited to 'server/server.go')
-rw-r--r-- | server/server.go | 78 |
1 files changed, 49 insertions, 29 deletions
diff --git a/server/server.go b/server/server.go index a833fa7f..f9976624 100644 --- a/server/server.go +++ b/server/server.go @@ -452,7 +452,7 @@ func (server *BgpServer) Serve() { t.Stop() }(addr) - m := server.dropPeerAllRoutes(peer) + m := server.dropPeerAllRoutes(peer, peer.configuredRFlist()) if len(m) > 0 { senderMsgs = append(senderMsgs, m...) } @@ -580,11 +580,11 @@ func filterpath(peer *Peer, path *table.Path) *table.Path { return path } -func (server *BgpServer) dropPeerAllRoutes(peer *Peer) []*SenderMsg { +func (server *BgpServer) dropPeerAllRoutes(peer *Peer, families []bgp.RouteFamily) []*SenderMsg { msgs := make([]*SenderMsg, 0) options := &table.PolicyOptions{} - for _, rf := range peer.configuredRFlist() { + for _, rf := range families { dsts := server.globalRib.DeletePathsByPeer(peer.fsm.peerInfo, rf) server.validatePaths(dsts, true) if peer.isRouteServerClient() { @@ -957,10 +957,26 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) []*SenderMsg { if t.Sub(time.Unix(peer.conf.Timers.State.Uptime, 0)) < FLOP_THRESHOLD { peer.conf.State.Flops++ } - + var drop []bgp.RouteFamily + if peer.fsm.reason == FSM_GRACEFUL_RESTART { + peer.fsm.pConf.GracefulRestart.State.PeerRestarting = true + var p []bgp.RouteFamily + p, drop = peer.forwardingPreservedFamilies() + peer.StaleAll(p) + } else { + drop = peer.configuredRFlist() + } + peer.DropAll(drop) + msgs = append(msgs, server.dropPeerAllRoutes(peer, drop)...) + } else if peer.fsm.pConf.GracefulRestart.State.PeerRestarting && nextState == bgp.BGP_FSM_IDLE { + // RFC 4724 4.2 + // If the session does not get re-established within the "Restart Time" + // that the peer advertised previously, the Receiving Speaker MUST + // delete all the stale routes from the peer that it is retaining. + peer.fsm.pConf.GracefulRestart.State.PeerRestarting = false peer.DropAll(peer.configuredRFlist()) - msgs = append(msgs, server.dropPeerAllRoutes(peer)...) + msgs = append(msgs, server.dropPeerAllRoutes(peer, peer.configuredRFlist())...) } close(peer.outgoing) @@ -1072,6 +1088,14 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) []*SenderMsg { } if len(eor) > 0 { + for _, f := range eor { + for i, a := range peer.fsm.pConf.AfiSafis { + if g, _ := bgp.GetRouteFamily(string(a.AfiSafiName)); f == g { + peer.fsm.pConf.AfiSafis[i].MpGracefulRestart.State.EndOfRibReceived = true + } + } + } + // RFC 4724 4.1 // Once the session between the Restarting Speaker and the Receiving // Speaker is re-established, ...snip... it MUST defer route @@ -1080,33 +1104,17 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) []*SenderMsg { // "Restart State" bit set in the received capability and excluding the // ones that do not advertise the graceful restart capability) or ...snip... if peer.fsm.pConf.GracefulRestart.State.LocalRestarting { - var end bool - for _, f := range eor { - end = true - for i, a := range peer.fsm.pConf.AfiSafis { - if g, _ := bgp.GetRouteFamily(string(a.AfiSafiName)); f == g { - peer.fsm.pConf.AfiSafis[i].MpGracefulRestart.State.EndOfRibReceived = true - } - if s := a.MpGracefulRestart.State; s.Enabled && !s.EndOfRibReceived { - end = false + allEnd := func() bool { + for _, p := range server.neighborMap { + if !p.recvedAllEOR() { + return false } } - } - if end { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": peer.conf.Config.NeighborAddress, - }).Debug("all family's EOR received") - peer.fsm.pConf.GracefulRestart.State.LocalRestarting = false - } - allEnd := true - for _, p := range server.neighborMap { - if p.fsm.pConf.GracefulRestart.State.LocalRestarting { - allEnd = false - } - } + return true + }() if allEnd { for _, p := range server.neighborMap { + p.fsm.pConf.GracefulRestart.State.LocalRestarting = false if !p.isGracefulRestartEnabled() { continue } @@ -1121,6 +1129,18 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) []*SenderMsg { }).Info("sync finished") } } + if peer.fsm.pConf.GracefulRestart.State.PeerRestarting { + if peer.recvedAllEOR() { + peer.fsm.pConf.GracefulRestart.State.PeerRestarting = false + pathList := peer.adjRibIn.DropStale(peer.configuredRFlist()) + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": peer.conf.Config.NeighborAddress, + }).Debugf("withdraw %d stale routes", len(pathList)) + m, _ := server.propagateUpdate(peer, pathList) + msgs = append(msgs, m...) + } + } } default: log.WithFields(log.Fields{ @@ -2381,7 +2401,7 @@ func (server *BgpServer) handleGrpcModNeighbor(grpcReq *GrpcRequest) (sMsgs []*S n.fsm.t.Wait() t.Stop() }(addr) - m := server.dropPeerAllRoutes(n) + m := server.dropPeerAllRoutes(n, n.configuredRFlist()) if len(m) > 0 { sMsgs = append(sMsgs, m...) } |