diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-07-13 12:49:17 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-07-14 21:13:09 +0900 |
commit | 72d1fc4cedd233861df725a9eac5f18022f92125 (patch) | |
tree | 75843a9609fd77acef784d535b419e3e6bcf15d6 /server/fsm.go | |
parent | 16aec4acef8f580b7b1b62abedc6365c176feb3f (diff) |
server: fix fsm.keepaliveTicker race
When fsm state goes to idle from established, fsm.keepaliveTicker is
set to nil. This can happen before <-h.t.Dying() case in
sendMessageloop().
This removes fsm.keepaliveTicker. Ticker is created locally. With
this, a keepalive message could be sent from openconfirm to
established with a shorter interval. But it should not break anything.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Diffstat (limited to 'server/fsm.go')
-rw-r--r-- | server/fsm.go | 36 |
1 files changed, 18 insertions, 18 deletions
diff --git a/server/fsm.go b/server/fsm.go index 749c925b..c25fd1f3 100644 --- a/server/fsm.go +++ b/server/fsm.go @@ -68,7 +68,6 @@ type FSM struct { t tomb.Tomb globalConfig *config.Global peerConfig *config.Neighbor - keepaliveTicker *time.Ticker state bgp.FSMState conn net.Conn connCh chan net.Conn @@ -280,13 +279,6 @@ func NewFSMHandler(fsm *FSM, incoming chan *fsmMsg, outgoing chan *bgp.BGPMessag func (h *FSMHandler) idle() bgp.FSMState { fsm := h.fsm - if fsm.keepaliveTicker != nil { - if fsm.negotiatedHoldTime != 0 { - fsm.keepaliveTicker.Stop() - } - fsm.keepaliveTicker = nil - } - idleHoldTimer := time.NewTimer(time.Second * time.Duration(fsm.idleHoldTime)) for { select { @@ -575,9 +567,23 @@ func (h *FSMHandler) opensent() bgp.FSMState { } } +func keepaliveTicker(fsm *FSM) *time.Ticker { + if fsm.negotiatedHoldTime == 0 { + return &time.Ticker{} + } + sec := time.Second * time.Duration(fsm.peerConfig.Timers.KeepaliveInterval) + if fsm.negotiatedHoldTime < fsm.peerConfig.Timers.HoldTime { + sec = time.Second * time.Duration(fsm.negotiatedHoldTime) / 3 + } + if sec == 0 { + sec = 1 + } + return time.NewTicker(sec) +} + func (h *FSMHandler) openconfirm() bgp.FSMState { fsm := h.fsm - + ticker := keepaliveTicker(fsm) h.msgCh = make(chan *fsmMsg) h.conn = fsm.conn @@ -585,15 +591,8 @@ func (h *FSMHandler) openconfirm() bgp.FSMState { var holdTimer *time.Timer if fsm.negotiatedHoldTime == 0 { - fsm.keepaliveTicker = &time.Ticker{} holdTimer = &time.Timer{} } else { - sec := time.Second * time.Duration(fsm.peerConfig.Timers.KeepaliveInterval) - if fsm.negotiatedHoldTime < fsm.peerConfig.Timers.HoldTime { - sec = time.Second * time.Duration(fsm.negotiatedHoldTime) / 3 - } - fsm.keepaliveTicker = time.NewTicker(sec) - // RFC 4271 P.65 // sets the HoldTimer according to the negotiated value holdTimer = time.NewTimer(time.Second * time.Duration(fsm.negotiatedHoldTime)) @@ -613,7 +612,7 @@ func (h *FSMHandler) openconfirm() bgp.FSMState { "Topic": "Peer", "Key": fsm.peerConfig.NeighborAddress, }).Warn("Closed an accepted connection") - case <-fsm.keepaliveTicker.C: + case <-ticker.C: m := bgp.NewBGPKeepAliveMessage() b, _ := m.Serialize() // TODO: check error @@ -676,6 +675,7 @@ func (h *FSMHandler) openconfirm() bgp.FSMState { func (h *FSMHandler) sendMessageloop() error { conn := h.conn fsm := h.fsm + ticker := keepaliveTicker(fsm) send := func(m *bgp.BGPMessage) error { b, err := m.Serialize() if err != nil { @@ -748,7 +748,7 @@ func (h *FSMHandler) sendMessageloop() error { if err := send(m); err != nil { return nil } - case <-fsm.keepaliveTicker.C: + case <-ticker.C: if err := send(bgp.NewBGPKeepAliveMessage()); err != nil { return nil } |