summaryrefslogtreecommitdiffhomepage
path: root/server/fsm.go
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2016-02-10 23:41:44 -0800
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-02-10 23:41:44 -0800
commit023a498e4a90982095c870c5491770bf4952fc2b (patch)
tree135c11a05d8ff106264d91f0965aa6d926ac861b /server/fsm.go
parentb19bbd415e8d33f01bcd407baece94ea1b81c957 (diff)
server: support graceful-restart helper-speaker behavior
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
Diffstat (limited to 'server/fsm.go')
-rw-r--r--server/fsm.go112
1 files changed, 81 insertions, 31 deletions
diff --git a/server/fsm.go b/server/fsm.go
index aa0d7d4e..8a8748a5 100644
--- a/server/fsm.go
+++ b/server/fsm.go
@@ -116,24 +116,25 @@ func (s AdminState) String() string {
}
type FSM struct {
- t tomb.Tomb
- gConf *config.Global
- pConf *config.Neighbor
- state bgp.FSMState
- reason FsmStateReason
- conn net.Conn
- connCh chan net.Conn
- idleHoldTime float64
- opensentHoldTime float64
- adminState AdminState
- adminStateCh chan AdminState
- getActiveCh chan struct{}
- h *FSMHandler
- rfMap map[bgp.RouteFamily]bool
- capMap map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface
- recvOpen *bgp.BGPMessage
- peerInfo *table.PeerInfo
- policy *table.RoutingPolicy
+ t tomb.Tomb
+ gConf *config.Global
+ pConf *config.Neighbor
+ state bgp.FSMState
+ reason FsmStateReason
+ conn net.Conn
+ connCh chan net.Conn
+ idleHoldTime float64
+ opensentHoldTime float64
+ adminState AdminState
+ adminStateCh chan AdminState
+ getActiveCh chan struct{}
+ h *FSMHandler
+ rfMap map[bgp.RouteFamily]bool
+ capMap map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface
+ recvOpen *bgp.BGPMessage
+ peerInfo *table.PeerInfo
+ policy *table.RoutingPolicy
+ gracefulRestartTimer *time.Timer
}
func (fsm *FSM) bgpMessageStateUpdate(MessageType uint8, isIn bool) {
@@ -191,19 +192,21 @@ func NewFSM(gConf *config.Global, pConf *config.Neighbor, policy *table.RoutingP
adminState = ADMIN_STATE_DOWN
}
fsm := &FSM{
- gConf: gConf,
- pConf: pConf,
- state: bgp.BGP_FSM_IDLE,
- connCh: make(chan net.Conn, 1),
- opensentHoldTime: float64(HOLDTIME_OPENSENT),
- adminState: adminState,
- adminStateCh: make(chan AdminState, 1),
- getActiveCh: make(chan struct{}),
- rfMap: make(map[bgp.RouteFamily]bool),
- capMap: make(map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface),
- peerInfo: table.NewPeerInfo(gConf, pConf),
- policy: policy,
+ gConf: gConf,
+ pConf: pConf,
+ state: bgp.BGP_FSM_IDLE,
+ connCh: make(chan net.Conn, 1),
+ opensentHoldTime: float64(HOLDTIME_OPENSENT),
+ adminState: adminState,
+ adminStateCh: make(chan AdminState, 1),
+ getActiveCh: make(chan struct{}),
+ rfMap: make(map[bgp.RouteFamily]bool),
+ capMap: make(map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface),
+ peerInfo: table.NewPeerInfo(gConf, pConf),
+ policy: policy,
+ gracefulRestartTimer: time.NewTimer(time.Hour),
}
+ fsm.gracefulRestartTimer.Stop()
fsm.t.Go(fsm.connectLoop)
return fsm
}
@@ -285,7 +288,7 @@ func (fsm *FSM) connectLoop() error {
ticker.Stop()
connect := func() {
- if fsm.state == bgp.BGP_FSM_ACTIVE {
+ if fsm.state == bgp.BGP_FSM_ACTIVE && !fsm.pConf.GracefulRestart.State.PeerRestarting {
addr := fsm.pConf.Config.NeighborAddress
host := net.JoinHostPort(addr, strconv.Itoa(bgp.BGP_PORT))
// check if LocalAddress has been configured
@@ -376,6 +379,15 @@ func (h *FSMHandler) idle() (bgp.FSMState, FsmStateReason) {
select {
case <-h.t.Dying():
return -1, FSM_DYING
+ case <-fsm.gracefulRestartTimer.C:
+ if fsm.pConf.GracefulRestart.State.PeerRestarting {
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": fsm.pConf.Config.NeighborAddress,
+ "State": fsm.state,
+ }).Warn("graceful restart timer expired")
+ return bgp.BGP_FSM_IDLE, FSM_RESTART_TIMER_EXPIRED
+ }
case conn, ok := <-fsm.connCh:
if !ok {
break
@@ -440,6 +452,15 @@ func (h *FSMHandler) active() (bgp.FSMState, FsmStateReason) {
// we don't implement delayed open timer so move to opensent right
// away.
return bgp.BGP_FSM_OPENSENT, 0
+ case <-fsm.gracefulRestartTimer.C:
+ if fsm.pConf.GracefulRestart.State.PeerRestarting {
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": fsm.pConf.Config.NeighborAddress,
+ "State": fsm.state,
+ }).Warn("graceful restart timer expired")
+ return bgp.BGP_FSM_IDLE, FSM_RESTART_TIMER_EXPIRED
+ }
case err := <-h.errorCh:
return bgp.BGP_FSM_IDLE, err
case s := <-fsm.adminStateCh:
@@ -708,6 +729,15 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) {
"Key": fsm.pConf.Config.NeighborAddress,
"State": fsm.state,
}).Warn("Closed an accepted connection")
+ case <-fsm.gracefulRestartTimer.C:
+ if fsm.pConf.GracefulRestart.State.PeerRestarting {
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": fsm.pConf.Config.NeighborAddress,
+ "State": fsm.state,
+ }).Warn("graceful restart timer expired")
+ return bgp.BGP_FSM_IDLE, FSM_RESTART_TIMER_EXPIRED
+ }
case e := <-h.msgCh:
switch e.MsgData.(type) {
case *bgp.BGPMessage:
@@ -868,6 +898,15 @@ func (h *FSMHandler) openconfirm() (bgp.FSMState, FsmStateReason) {
"Key": fsm.pConf.Config.NeighborAddress,
"State": fsm.state,
}).Warn("Closed an accepted connection")
+ case <-fsm.gracefulRestartTimer.C:
+ if fsm.pConf.GracefulRestart.State.PeerRestarting {
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": fsm.pConf.Config.NeighborAddress,
+ "State": fsm.state,
+ }).Warn("graceful restart timer expired")
+ return bgp.BGP_FSM_IDLE, FSM_RESTART_TIMER_EXPIRED
+ }
case <-ticker.C:
m := bgp.NewBGPKeepAliveMessage()
b, _ := m.Serialize()
@@ -1031,6 +1070,8 @@ func (h *FSMHandler) established() (bgp.FSMState, FsmStateReason) {
holdTimer = time.NewTimer(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime))
}
+ fsm.gracefulRestartTimer.Stop()
+
for {
select {
case <-h.t.Dying():
@@ -1048,6 +1089,15 @@ func (h *FSMHandler) established() (bgp.FSMState, FsmStateReason) {
case err := <-h.errorCh:
h.conn.Close()
h.t.Kill(nil)
+ if s := fsm.pConf.GracefulRestart.State; s.Enabled && (err == FSM_READ_FAILED || err == FSM_WRITE_FAILED) {
+ err = FSM_GRACEFUL_RESTART
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": fsm.pConf.Config.NeighborAddress,
+ "State": fsm.state,
+ }).Info("peer graceful restart")
+ fsm.gracefulRestartTimer.Reset(time.Duration(fsm.pConf.GracefulRestart.State.PeerRestartTime) * time.Second)
+ }
return bgp.BGP_FSM_IDLE, err
case <-holdTimer.C:
log.WithFields(log.Fields{